I am trying to run an application in which I am using JPQL. In the beginning of the application, I am running,
public class CacheManager {
private static final Logger LOGGER = LoggerFactory.getLogger(CacheManager.class);
private static ConcurrentHashMap<String, Student> temp;
public static void initLoadingCache(StudentDAO dao) {
LOGGER.debug("Fetching...");
List<Student> students = dao.findAll();
}
where the findall() is as follows alongwith its query:
public List<Student> findAll() {
return namedQuery("Student.findAll").getResultList();
}
where the query is like:
#Entity
#Table(name = "Student")
#NamedQueries({
#NamedQuery(
name = "Student.findAll",
query = "SELECT p FROM Student p")
)})
I keep getting org.hibernate.HibernateException: No session currently bound to execution context but I am not sure why I get this for this particular query even though I am not doing multithreading or any Async calls. Any fix would help a lot.
Entire stacktrace:
org.hibernate.HibernateException: No session currently bound to execution context
at org.hibernate.context.internal.ManagedSessionContext.currentSession(ManagedSessionContext.java:58)
at org.hibernate.internal.SessionFactoryImpl.getCurrentSession(SessionFactoryImpl.java:464)
at io.dropwizard.hibernate.AbstractDAO.currentSession(AbstractDAO.java:44)
at io.dropwizard.hibernate.AbstractDAO.namedQuery(AbstractDAO.java:76)
at com.xyz.abc.student.db.StudentDAO.findAll(StudentDAO.java:26)
at com.xyz.abc.student.db.CacheManager.initLoadingCache(CacheManager.java:24)
at com.xyz.abc.student.StudentService.run(StudentService.java:118)
at com.xyz.abc.student.StudentService.run(StudentService.java:43)
at io.dropwizard.cli.EnvironmentCommand.run(EnvironmentCommand.java:43)
at io.dropwizard.cli.ConfiguredCommand.run(ConfiguredCommand.java:87)
at io.dropwizard.cli.Cli.run(Cli.java:78)
at io.dropwizard.Application.run(Application.java:93)
at com.xyz.abc.student.StudentService.main(StudentService.java:46)
I further tried this which works
public StudentDAO(SessionFactory factory, int queryTimeout) {
super(factory);
sessionFactory = factory;
this.queryTimeout = queryTimeout;
}
public List<Student> findAll() throws Exception{
List<Student> students = null;
Session session = sessionFactory.openSession();
try {
ManagedSessionContext.bind(session);
Transaction transaction = session.beginTransaction();
try {
students = list((Query<Student>) namedQuery("Student.findAll"));
transaction.commit();
}
catch (Exception e) {
transaction.rollback();
throw new Exception(e.getMessage());
}
} finally {
session.close();
ManagedSessionContext.unbind(sessionFactory);
}
return students;
}
Try adding #UnitOfWork on your findAll method.
See the documentation for more information
To use the DAO classes in Dropwizard, you can just use the #UnitOfWork annotation in Jersey resources, but elsewhere you need to additionally instantiate your class with UnitOfWorkAwareProxyFactory. It will create a proxy of your class, which will open a Hibernate session with a transaction around methods with the #UnitOfWork annotation. (Dropwizard documentation)
One example is here: How to use UnitOfWorkAwareProxyFactory in Dropwizard v1.1.0
I'm learning about #Transactional and I want to ask you a question. Why is important to use #Transactional at the following methods?
#Repository
public class CustomerDAOImpl implements CustomerDAO {
// need to inject the session factory
#Autowired
private SessionFactory sessionFactory;
#Override
#Transactional
public List<Customer> getCustomers() {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// create a query ... sort by last name
Query<Customer> theQuery =
currentSession.createQuery("from Customer order by lastName",
Customer.class);
// execute query and get result list
List<Customer> customers = theQuery.getResultList();
// return the results
return customers;
}
#Override
#Transactional
public void saveCustomer(Customer theCustomer) {
// get current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// save/upate the customer ... finally LOL
currentSession.saveOrUpdate(theCustomer);
}
#Override
#Transactional
public Customer getCustomer(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// now retrieve/read from database using the primary key
Customer theCustomer = currentSession.get(Customer.class, theId);
return theCustomer;
}
#Override
#Transactional
public void deleteCustomer(int theId) {
// get the current hibernate session
Session currentSession = sessionFactory.getCurrentSession();
// delete object with primary key
Query theQuery =
currentSession.createQuery("delete from Customer where id=:customerId");
theQuery.setParameter("customerId", theId);
theQuery.executeUpdate();
}
}
I thought that we need to use #Transactional when we have 2 or more writes on a database. For example if we want to transfer $100 from user A to user B. In this case we need to do 2 things, first we need to decrease $100 from user A, and second we need to add $100 to user B. And we need this 2 writes as a single atomic operation. And I understand why we need #Transactional in this situation.
But what I don't understand is why do we need #Transactional for the 4 methods in the above code. In getCustomers() method we just retrieve the customers, in saveCustomer() we just save a customer in the database, deleteCustomer() we just delete a customer. So in these methods we have only one write in the database. Then why do we need #Transactional? Thank you!
Do anyone know how to solve this problem?? I am trying to delete an entity but this error message always appears.
This is the code used:
#Override
public void remove(t_diklat diklat) {
Session session = HibernateUtil.getSessionFactory().openSession();
try {
session.getTransaction().begin();
session.delete(diklat);
session.getTransaction().commit();
} catch (Exception ex) {
throw ex;
}
and:
public String delete() {
t_diklat diklat = (t_diklat)(listDiklat.getRowData());
diklatDao dao = new diklat_Impl();
dao.remove(diklat);
return "diklat_client";
}
This is my dao
public interface diklatDao {
public t_diklat getTbl_diklat(Long id);
public void Save(t_diklat diklat);
public void remove(t_diklat diklat);
public void update(t_diklat diklat);
public List<t_diklat> ListTable();
}
I also add #OneToMany(mappedBy = "diklat_id_5", cascade = CascadeType.ALL) to my model.class but still nothing.
I am quite sure that the:
public String delete()
method is called within an already opened session as you are retrieving data:
t_diklat diklat = (t_diklat)(listDiklat.getRowData());
just before you hit the dao.remove() method.
Inside the dao, you open another session and try pass an entity that is already associated with the presiously opened and still not closed session.
The solution would be to use:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
instead of:
Session session = HibernateUtil.getSessionFactory().openSession();
Edit:
Try not to open any new transactions and do not perform a commit in the dao. The outer session management should be enough.. So in your dao just:
Session session = HibernateUtil.getSessionFactory().getCurrentSession();
session.delete(diklat);
I have Java EE application with Hibernate. I want to implement a feature that every minute updates one of existing rows in database. I have following classes:
#Singleton
#Startup
public class TimerRunnerImpl implements TimerRunner {
#EJB
private WorkProcessor workProcessor;
private String jobId;
#Timeout
#AccessTimeout(value = 90, unit = TimeUnit.MINUTES)
#TransactionAttribute(value = TransactionAttributeType.NEVER)
public void doProcessing(Timer timer) {
jobId = workProcessor.doWork(jobId);
}
//other methods: startTimer, etc
}
#Stateless
public class WorkProcessorImpl implements WorkProcessor {
#EJB
private MyEntityDao myEntityDao;
#TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
#Override
public String doWork(String jobId) {
if (jobId == null) {
MyEntity myEntity = myEntityDao.oldestEntityToProcess();
String uuid = UUID.randomUUID().toString();
myEntity.setJobId(uuid);
myEntityDao.update(myEntity); // this invokes merge()
return uuid;
} else {
// line below can never find entity, although there is one in DB
MyEntity myEntity = myEntityDao.findByJobId(jobId);
myEntity.setSomeProperty("someValue");
// some other updates
myEntityDao.update(myEntity); // this invokes merge()
return jobId;
}
}
}
First run of doWork updates MyEntity with job ID. This is being persisted into database - I can query it manually from SQLDeveloper. Second run always fails to find entity by job ID. In case I try to retrieve it by entity_id in debug mode, the object retrieved from Entity Manager has job id with previous value.
This is not cache problem, I have tried on each run to evict all cache at the beginning and results are identical.
As far as I understand, transaction is around workProcessor.doWork(jobId). I find confirmation of this by the fact that when this method returns I can see changes in DB. But why does EntityManager keeps my unmodified object and returns it when I query for it?
Hello everyone here is my DAO class :
public class UsersDAO extends HibernateDaoSupport {
private static final Log log = LogFactory.getLog(UsersDAO.class);
protected void initDao() {
//do nothing
}
public void save(User transientInstance) {
log.debug("saving Users instance");
try {
getHibernateTemplate().saveOrUpdate(transientInstance);
log.debug("save successful");
} catch (RuntimeException re) {
log.error("save failed", re);
throw re;
}
}
public void update(User transientInstance) {
log.debug("updating User instance");
try {
getHibernateTemplate().update(transientInstance);
log.debug("update successful");
} catch (RuntimeException re) {
log.error("update failed", re);
throw re;
}
}
public void delete(User persistentInstance) {
log.debug("deleting Users instance");
try {
getHibernateTemplate().delete(persistentInstance);
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
public User findById( java.lang.Integer id) {
log.debug("getting Users instance with id: " + id);
try {
User instance = (User) getHibernateTemplate()
.get("project.hibernate.Users", id);
return instance;
} catch (RuntimeException re) {
log.error("get failed", re);
throw re;
}
}
}
Now I wrote a test class(not a junit test) to test is everything working, my user has these fields in the database : userID which is 5characters long string and unique/primary key, and fields such as address, dob etc(total 15 columns in database table). Now in my test class I intanciated User added the values like :
User user = new User;
user.setAddress("some address");
and so I did for all 15 fields, than at the end of assigning data to User object I called in DAO to save that to database UsersDao.save(user); and save works just perfectly. My question is how do I update/delete users using the same logic?
Fox example I tried this(to delete user from table users):
User user = new User;
user.setUserID("1s54f"); // which is unique key for users no two keys are the same
UsersDao.delete(user);
I wanted to delete user with this key but its obviously different can someone explain please how to do these. thank you
UPDATE :
Do I need to set all 15 fields on User object to delete it like I did with save method ?
Having not looked at Hibernate for quite a while now, I can only hazard a guess at the problem.
It seems that you are creating a User object, but only populating the User ID field, so the persistence layer knows nothing about the actual User.
I would recommend using a retrieve function that can find the User with the given ID, and then pass that User into the delete method.
User u = UsersDao.findById("1s54f");
UsersDao.delete(u);
This should work, as the persistence layer will know about the User, so it has all of the details it needs to perform the delete.
However, a more efficient method would be to find a way of deleting a user by ID, so you do not have to query the database to get the instance of the User and then delete it.
Hope this helps.
Chris
In an ideal world you will have your model's business key as the database primary key and you'll not have this problem. But it ain't so, isn't it?
For you particular problem if you are very much sure that the userID is going to be unique then you can try this (taken from here):
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlDelete = "delete User u where u.userID = :id";
int deletedEntities = s.createQuery( hqlDelete )
.setString( "id", userID )
.executeUpdate();
tx.commit();
session.close();
But let me warn you. This kind of code is not good at all. For example what happens if you decide in future that the column you used in delete is no longer unique? Then you'll run into a very serious bug or a very bad case of refactoring. Either way the fool-proof (may not be efficient & may not be feasible) way is to delete records based on their primary key.
Check out the documentation. Get used to the concept of persistent, transient, and detached instances. To delete an instance, you call
session.delete(persistentInstance)
and to update (although you probably shouldn't need to use it), call
persistentInstance = session.merge(detachedInstance)
Shouldn't need to use update? No, because you just need to load/find an object first, and then modify it. Any modifications you make to a persistent object will automatically be saved back to the database.
In order to delete the user that its ID is "1s54f" you should create a delete HQL as follows:
public void delete(String id) {
log.debug("deleting Users instance");
try {
final String deleteQuery = "delete from User where id = :id";
final Query query = getSession().createQuery(deleteQuery);
final query.setString("id",id);
final int rowCount = query.executeUpdate(); // check that the rowCount is 1
log.debug("delete successful");
} catch (RuntimeException re) {
log.error("delete failed", re);
throw re;
}
}
Then you can use this method like:
userDao.delete("1s54f");
Hope this helps.
Hibernate is an object-relational mapper, that is, it translates between the world of relational databases and object-oriented Java code. Since primary keys are a database concept, it is hibernate's job to translate them into object-oriented terms (in this case: object identity).
That is, if you pass primary keys to hibernate, you are not using hibernate as intended; calling code should represent persistent data with mapped objects, not primary keys. This also allows hibernate to automatically guard against lost updates by checking version numbers.
The typical pattern therefore is to have the following signature:
interface UserDAO {
void delete(User user);
}
and require the DAOs caller to come up with a persistent object to pass to it. The caller might have such an object lying about from the current or a previous (now closed) session, after all, he did somehow learn about its primary key. If all else fails, you can use session.load(User.class, id) to ask hibernate for a proxy to pass to the delete method. (Note that one shouldn't use session.load if the object might no longer exist in the database.)
It's not necessary fetch a whole entity before removing it, neither create a hardcoded query for delete, nor setting every field in entity.
Maybe better way to do that is setting the id for entity and use Hibernate API itself.
If a specific dao is used to entity User, as described in question, try:
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
User user = new User();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(user, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
As can be seen, neither unnecessary operation in database is made.
And this can be used in generic flavor if GenericDao is implemented like:
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
Model entity = entityClass.newInstance();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(entity, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
Both ways, Dao must extend org.springframework.orm.hibernate4.support.HibernateDaoSupport to get advantages.
Here's a fragment of generic:
public class GenericDaoImpl<Model> extends HibernateDaoSupport implements GenericDao<Model> {
private Class<Model> entityClass;
public GenericDaoImpl() {
this.entityClass = (Class<Model>) ((ParameterizedType) getClass().getGenericSuperclass()).getActualTypeArguments()[0];
}
/* CRUD are implemented here */
public void remove(Serializable id) throws InstantiationException, IllegalAccessException {
Model entity = entityClass.newInstance();
getSessionFactory().getClassMetadata(getEntityClass()).setIdentifier(entity, id, (SessionImplementor) getSessionFactory().getCurrentSession());
getHibernateTemplate().delete(entity);
}
}