Question

I have following problem. I use JBoss 5.1, JPA/Hibernate with 2-nd level cache. My system has few entities mapping the same database table. Example: Table FURNITURES is mapped by entity 'Furn' and 'Furniture'.

These classes CAN NOT be changed.

Now the when i change the data of 'Furn' with id 1, the 'Furniture' with id 1 still has the old data. Is there some possibility to evict 'Furniture' after 'Furn' was updated?

Was it helpful?

Solution

When you update/delete your object, a notification is sent to the caching layer to reflect those changes.

The cache key might even be broadcasted to another server so it has to carry enough payload to provide enough information for the remote end to flush the relevant entry. But on the other hand it can not be too big in order maximise the throughput.

If you turn on the debugging, you will see the following structure (it might vary depending on your persistent object type, identifier - composite or not, etc.):

cacheKey = {org.hibernate.cache.CacheKey}
|- key = {your.own.serializable.class}
|- type = {org.hibernate.type.ComponentType}
| |- typeScope = {org.hibernate.type.TypeFactory$TypeScopeImpl}
| | |- factory = {org.hibernate.impl.SessionFactoryImpl}
| |- propertyNames = {...}
| |- propertyTypes = {...}
| |- propertyNullability = {...}
| |- propertySpan = 2
| |- cascade = {...}
| |- joinedFetch = {...}
| |- isKey = true
| |- tuplizerMapping = {...}
|- entityOrRoleName = {java.lang.String} "my.Entity"
|- entityMode = {org.hibernate.EntityMode}
|- hashCode = 588688

As you can see, Hibernate cache key stores information about the class name, id type, etc. If you have two different types, they will be mapped to two different cache keys hence your problem.

In order to fix it, you can create DAO classes for both entities and ensure all calls to persist those entities only go through them and nowhere else. Then, in the update/delete method of both entries simply load and evict the other entity.

Another option is to use interceptors which can help achieving the same functionality but to my taste the DAO path is cleaner.

OTHER TIPS

Mapping same table to two entities is not recommended, so I don't think hibernate will handle this automatically.

You can implement a post-flush listener for Furn entity and then use something like the below code to evict the corresponding Furniture object

// This creates a proxy if not already loaded 
// other gives the object
Furniture furniture = session.load(Furniture.class,furn.getId());
// remove from first level cache
session.evict(furniture);
// remove from second level cache
sessionFactory.evict(Furniture.class,furn.getId());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top