Archive for August, 2007

Dammit Hibernate, that data is stale!

Tuesday, August 21st, 2007

Problem

A user operation has changed the status of some entities in our database. Hibernate, while wonderful and all, is retrieving stale data from its cache instead of from the database. How do we force Hibernate to look at the database, or realise that the data has changed?

Solution

Well, first and foremost, this isn’t Hibernate’s problem. From http://forum.java.sun.com/thread.jspa?threadID=700590&start=15&tstart=0

“hibernate can’t magically know when the data changes in the database, how can you expect it to notify your application?”

The system I’m working on has a long-session setup, where the underlying database can be modified without Hibernate’s knowledge. This would seem to be a problem other people have encountered:

“The long EDT session caches fetched objects. What if the database changes from outside the application and you want to display the changed data? Your only chance is to close the session, delete all objects, which were attached to the old session and are potentially stale, open a new long session and retrieve all the data to be displayed again.” http://www.javalobby.org/java/forums/t20533.html

So, this particular developer recommends closing the session and opening it again. The problem being for me, that there are other objects in this session that will be potentially lost when it is closed and reopened again; not to mention the chance that a user somewhere else may try to make a change impacting the session while a session is closed! Which brings us to Session.refresh(Object):

“* Refresh() is OK for telling HIbernate to update the in-memory contents of the object, but there are three problems with it. One is that there is a bug with cascading refreshes, so that if you try to refresh an object that has a to-many association where one of the items in the collection has been removed on the server, it will fail with an exception. This is not too bad, you can solve it by disabling cascades and doing it all manually. Two is also a minor point, which is that the docs recommend not using this method. They don’t say why. Three is that it does an immediate SQL fetch for each refreshed object, so it is very inefficient to refresh batches of objects, and since there is no refreshing query capability (see first point), there is no efficient way that I can see to refresh a list of items. This is especially bad with the prior point about sort ordering, because it means that I’m much more likely to need to have to refresh all the items in a list.”
http://forum.java.sun.com/thread.jspa?threadID=700590&start=15&tstart=0

“If you want reload objects which changed out of hibernate (database triggers, other application etc) you can use : session.refresh(ent).
Unfortunately, you have to refresh only one object/entity with this method, but it’s only what hibernate offer - hibernate have great caching mechanism and refreshing complete session can be performace downgrade.
You can call rebuild session factory, of course, but it is time consuming operation.”
http://www.myeclipseide.com/PNphpBB2+file-viewtopic-t-13552.html

Very well. Looks like it might be time for me to try refresh(). My one concern however is that it’s only for one object; and my database is modified by an import operation, so when 100,000 items are imported… well, let’s just see how long that takes.