1
I am facing problems with Hibernate that seems to be related to the cache object.
I have an entity, let’s call it A, with an attribute mapped list with @OneToMany (cascade = CascadeType.ALL, mappedBy = "atributo")
. The objects in the list are class B entities and have a bidirectional relationship with A. So B has an attribute mapped with @ManyToOne (cascade = CascadeType.MERGE)
. I receive object A from the database and add a new object B in list A using the call and Session.update(A)
.
The problem arises when I list all objects of type A, using the call session.createCriteria(A.class).list();
, access exactly to an A object that I updated and object B NAY is on the list. When opening Postgresql, both objects are updated and correctly saved, but sometimes in the query performed in the Criteria the data is not the same (sometimes they are correct and sometimes they are not).
I tried to use Session.refresh (A) after update A, but the problem still persists.
About the comment of Caffé, I believe that this is what is happening, but I still can not find a solution to the problem. Below follows the implementation of save and update methods of Genericdao:
** Note that our Genericdao class is broken down using Threadlocal.
private static final ThreadLocal threadSession = new ThreadLocal();
private static final ThreadLocal threadTransaction = new ThreadLocal();
public GenericDao(final Class<T> objectClass) {
this.objectClass = objectClass;
}
public Class<T> getObjectClass() {
return this.objectClass;
}
public T save(final T object) throws HibernateException {
try {
final Session s = this.getSessionHibernate();
s.beginTransaction();
s.save(object);
s.getTransaction().commit();
s.flush();
return object;
} catch (final HibernateException ex) {
GenericDao.logger.error(ex);
Session s = this.getSessionHibernate();
s.getTransaction().rollback();
s.clear();
throw new HibernateException(ex);
}
}
public void update(final T object) throws HibernateException {
try {
final Session s = this.getSessionHibernate();
s.update(object);
} catch (final HibernateException ex) {
GenericDao.logger.error(ex);
Session s = this.getSessionHibernate();
s.getTransaction().rollback();
s.clear();
throw new HibernateException(ex);
}
}
/**
* Get session opened of the Hibernate
*
* @return {@link Session}
*/
public Session getSessionHibernate() {
Session s = (Session) GenericDao.threadSession.get();
// Open a new Session, if this thread has none yet
if (s == null) {
s = this.getHibernateTemplate().getSessionFactory().openSession();
GenericDao.threadSession.set(s);
}
return s;
}
I tried to improve some formatting to make it easier to read, see if you can make it clearer to get better answers.
– Maniero
Consider that when you order an object, it is not always brought from the bank at that time - it can be brought from memory, so you will not see your child objects that have been added in another session. Also consider that when you persist an entity, it does not necessarily go to the bank at that time but at the end of the JPA transaction (it may go earlier if you give this order to the context, but if the JPA transaction is not terminated, the database transaction will be pending and the entity will not be seen in another context). Anyway,.
– Caffé
@Fernandochavesbenbassat You should also see the code that consumes this DAO, the code that obtains, alters and persists the objects. Probably this code is too big and sticking here would not help, so you would have to reproduce the problem in a separate environment (http://answall.com/help/mcve). In this exercise you may already kill the riddle. Now, in the title you say "instability" - if the problem only occurs once in a while, it must be related to the design of the threads (you’re using threads, right?).
– Caffé
@Fernandochavesbenbassat Another thing: why the method
save
initiates and commits the transaction and theupdate
No? Transaction management which is used by theupdate
may be causing the problem.– Caffé