views:

63

answers:

3

I have loaded an entity into my transaction and have changed a property of that entity. The transaction is not yet commited. Now I would like to get the original value of the changed property.

I've tried with a HQL query like select p.property from Person p where p.id = 1 with the ID of the entity loaded in the transaction.

I've set query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); before executing the query. But no success. Hibernate returns the value as set in the current transaction, not the one from the database.

Is there any way around this?

A: 

This may help:

If you want to force the query cache to refresh one of its regions (disregard any cached results it finds there) you can use org.hibernate.Query.setCacheMode(CacheMode.REFRESH). In conjunction with the region you have defined for the given query, Hibernate will selectively force the results cached in that particular region to be refreshed. This is particularly useful in cases where underlying data may have been updated via a separate process and is a far more efficient alternative to bulk eviction of the region via org.hibernate.SessionFactory.evictQueries().

(From http://docs.jboss.org/hibernate/stable/core/reference/en/html/performance.html, section 20.4.2).

However, is it intended to use when other process is updating the DB, and should be used with care. Your case is different. As this method occurs outside any transaction, you should be sure it does not conflict with your design. Maybe you can refactor your call flow to avoid that behavior, and retrieve the field from another source or before the modification in the cache takes place...

Sebastian
Reviewing my answer I see it does not fully address your problem. Even if you completely disable the second level cache, your entity data may be coming for the first level cache (session). For that, you should refresh or evict the object... but then you should re-enter the fields you want to save in the transaction commit.
Sebastian
A: 

The only way to do this would be to run the query outside of the current transaction.

james
A: 

I have loaded an entity into my transaction and have changed a property of that entity. The transaction is not yet commited. Now I would like to get the original value of the changed property.

In short: track the old value yourself.

I've tried with a HQL query like select p.property from Person p where p.id = 1 with the ID of the entity loaded in the transaction.

Hibernate loads a unique version of an entity into the session (the first level cache) for a given database identifier. This won't work.

I've set query.setHint("org.hibernate.cacheMode", CacheMode.IGNORE); before executing the query.

This hint is used to affect the query cache (that rely on the second-level-cache), this won't affect your current "issue".

Is there any way around this?

Either

  • use session.refresh() to force a reload of your entity (and you'll loose the changes)
  • store the previous value as initially mentioned.
  • invoke a service that perform a query in another transaction.
Pascal Thivent