Friday, February 11, 2011

Strange Hibernate Cache Issue

Hello

We are using Hibernate 3.1 with Spring MVC 2.0. Our problem occurs when data is updated on the database directly (not in the application). We use a Filter to filter a collection of results by whether the orders are opened or closed. If we change an order on the DB to be closed, the filter returns the correct list, however, the object's status does not change.

  • We do not have second-level or query caching enabled.
  • The retrieval of the collection from the DB is via Hibernate's Session.createQuery.
  • Also, we have one SessionFactory wired, and using one Session throughout the application.

The only time the object displays the correct status result is when the server is restarted--which we'd prefer not to have to do on a regular basis. Please offer any insight, and if any other information is required, please ask.

Thanks!

  • You can't really expect Hibernate to properly manage the "dirty" state of its cached objects when you have processes "going behind its back". If you're using annotations, I'd suggest marking the status (if that's the field's name) as @Transient, so that Hibernate knows it has to get this value from the database every time.

    Chris Serra : Thank you for a response. We are not using annotations at the moment, but will in the future, so I'll remember this :)
    Steve Moyer : You can mark a field as transient in your hbm files or as JavaDoc comments, but I don't remember how to do this anymore (only annotations now).
  • You probably want to enable the caching and set an expiry time. Then Hibernate will refresh data from the database once the cache has expired and someone has requested it.

    I use this on a home project as I occasionally tweak the database. I then wait a short while, refresh the page and see my tweaked data.

    Take a look at ehcache within Hibernate.

    Chris Serra : Ok, I will give this a try and let you know how it goes. Thanks for the response.
  • You may use versioning Hibernate Version. Your external process will have to increase the version number (or timestamp) to let Hibernate know a new version is available.

    This is not necessarily an immediate change, but occurs more often than a container restart (every few minutes in our case).

    It has a few disadvantages:

    • Your application may work for a while with old data
    • If the version has increased by a batch job, and hibernate tries to save an updated older version record, you will gen an exception
    • A shared database will scale less well; frequent checking does cost performance.

    I am by no means a Hibernate expert but it is possible.

    From extraneon
  • The Session always has a "first-level" cache, so if you're using one Session everything you read through it is going to be cached. Hibernate will execute the query against the database, but then as it's building the objects it checks the Session cache to avoid building a new object, so any columns changed in the database will not be refreshed. If you close it and get a new Session, it will read the full object from the database on the next query.

    Chris Serra : Yes, this is what I was looking for, a nice simple approach. Thank you.

0 comments:

Post a Comment