|
For an entity that inherits from another entity and has a lazily fetched property, the cache key for looking up that entity in the second level cache when initializing the lazy properties is constructed wrong: it uses the entity name, but should use the root entity name.
In org.hibernate.persister.entity.AbstractEntityPersister#initializeLazyProperty(java.lang.String, java.lang.Object, org.hibernate.engine.spi.SessionImplementor) the cache key is constructed like so:
...
if ( session.getCacheMode().isGetEnabled() && hasCache() ) {
final CacheKey cacheKey = session.generateCacheKey( id, getIdentifierType(), getEntityName() );
...
However, comparing other uses of session.generateCacheKey() e.g. org.hibernate.action.internal.EntityInsertAction#doAfterTransactionCompletion, an entity is stored in the second level cache by its root entity name. Consequently, cached entries for entities with inheritance will not be found in org.hibernate.persister.entity.AbstractEntityPersister#initializeLazyProperty(java.lang.String, java.lang.Object, org.hibernate.engine.spi.SessionImplementor).
As a side effect this will also leak memory with transactional caches in infinispan, as org.hibernate.cache.infinispan.access.TransactionalAccessDelegate#get will register a pending put that will not get cleaned up.
Corollary, the same may happen via org.hibernate.engine.spi.BatchFetchQueue#isCached(org.hibernate.engine.spi.EntityKey, org.hibernate.persister.entity.EntityPersister) that also has a suspicious call to session.generateCacheKey().
I unfortunately don't have any idea on how to provide a test case for this.
|