Dear Hibernate Community,
as I had to spend some time to solve the problem mentioned above I thought it might be helpful to post my solution (which is probably one of several possible approaches).
A source that was very helpful:
http://www.scribd.com/doc/35875415/Unde ... -HibernateThe difficult thing for me was to find a way to access an object the way it is still physically in the database without retrieving the (already altered) object from Java memory or Hibernate cache and without Hibernate flushing altered object to the DB before querying it.
Oracle triggers provide an easy way to compare objects in unaltered and altered states: REFERENCING NEW AS NEW OLD AS OLD
I was able to accomplish this the following way: Create a new Session and use the method
Code:
Session.load(Class arg0, Serializable arg1)
If the second level cache is NOT active it would then be possible to create the query and set the flush mode (only for this particular query) to COMMIT, thus the data would be queried without having changes flushed to the database first.
This would look approximat like that:
Code:
query = super.createQuery("SELECT o FROM " + FooObject.class.getName()
+ " o WHERE o.id = :id").setFlushMode(FlushModeType.COMMIT);
As in the project I am working on second level cache is used this was not an option (upon querying I retrieved the already altered object from Hibernate second lvl. cache) and
Code:
Session.load(Class arg0, Serializable arg1)
helped me out.
Please consider the object is retrieved using lazy loading, i.e. attributes are not loaded until the corresponding getter is invoked. Might be puzzling when debugging.
A short snippet to illustrate this wall of text: ;-)
Code:
@PreUpdate
public void FooObjectPreUpdate() {
FooObject objectAsInDatabase = null;
Session separateSession = getSession().getSessionFactory().openSession();
Long idOfAlteredObject = this.id; // as I am validating in the entity itself
objectAsInDatabase = (FooObject) separateSession.load(FooObject.class, idOfAlteredObject);
if (objectAsInDatabase != null) {
if (...) { // if a certain condition is fulfilled
this.setAnAttribute(objectAsInDatabase.getAnAttribute);
...
}
}
}
private Session getSession() {
final EntityManagerFactory entityManagerFactory = C.c().getCurrentEntityManagerFactory();
final EntityManager<?> entityManager = entityManagerFactory.getCurrentEntityManager();
EntityManagerHibernate entityManagerHibernate = (EntityManagerHibernate) entityManager;
Session session = entityManagerHibernate.getSession();
return session;
}
Hope this is helpful to someone and of course other ways of solving this problem or things that might be problematic when using this approach are very much appreciated!
It is certainly not the only way and even more certainly not the best way, but it worked fine for me. :-)
Kind regards,
Jana