hibernate继承缓存,CacheKey中使用的实体名称是否正确?

hai*_*Man 5 java inheritance caching hibernate ehcache

我有一个应用程序(spring/hibernate/ehcache 4.3.5 final),其中二级缓存适用于大多数对象.

但它似乎在TABLE_PER_CLASS继承模型中被打破,似乎对cachekey中的实体名称存在一些混淆,对象作为超类名称保存到区域中但是当它去检索对象时它正在使用子类名称.

所以我有2个班,一个超级和一个子...

@Entity
//@Indexed
@Audited(targetAuditMode=RelationTargetAuditMode.NOT_AUDITED)
@Inheritance (strategy = InheritanceType.TABLE_PER_CLASS)
@Table(name="group_link_entity")
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE  )
public abstract class GroupLinkEntity {

    @TableGenerator(
            name="sequenceGen", 
            table="database_sequence", 
            pkColumnName="GEN_KEY", 
            valueColumnName="GEN_VALUE", 
            pkColumnValue="ENTITY_ID",
            allocationSize=1)
    @Id 
    @GeneratedValue(strategy=GenerationType.TABLE, generator="sequenceGen")
    @Column(name = "ENTITY_ID")
    protected int id;
Run Code Online (Sandbox Code Playgroud)

@Entity
//@Indexed
@Audited(targetAuditMode=RelationTargetAuditMode.NOT_AUDITED)
@Table(name = "core_node")
public class Node extends GroupLinkEntity  implements Serializable {
Run Code Online (Sandbox Code Playgroud)

该地区将如预期的超级名称.第一次加载运行时,它将对象放入二级缓存中,我可以通过运行以下代码中的统计信息来查看

Map cacheEntries = ((Session) em.getDelegate()).getSessionFactory().getStatistics().getSecondLevelCacheStatistics(  element )
.getEntries();

if( cacheEntries.size() > 0 ){
    System.out.println( "  ...  " + cacheEntries ) ;        
}
Run Code Online (Sandbox Code Playgroud)

打印出......

   - com.core.dao.GroupLinkEntity
  ...  {1=CacheEntry(com.core.dao.Node)[........
Run Code Online (Sandbox Code Playgroud)

所以我知道带有PK 1的Node对象就在那里.

我第二次运行它并期望从缓存中获取对象,它将获得NonStrictReadWriteEhcacheEntityRegionAccessStrategy的get方法,我可以看到它在该区域中查找关键字...

com.core.dao.Node#1
Run Code Online (Sandbox Code Playgroud)

但是,如果我查看该区域中的缓存对象,我可以看到它所拥有的密钥是......

[com.core.dao.GroupLinkEntity#1]
Run Code Online (Sandbox Code Playgroud)

我知道它们都是同一个对象,但写作和阅读之间的某些东西是错误的.

该对象使用根名称存储在TwoPhaseLoad下...

final CacheKey cacheKey = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
Run Code Online (Sandbox Code Playgroud)

但是他们使用类名来创建cachekey,以便在DefaultLoadEventListener中进行检索...

final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getEntityName()
);
Run Code Online (Sandbox Code Playgroud)

文档很清楚,只应使用根名称来创建缓存键,所以我不确定这里发生了什么.对我来说,代码不起作用,因为它们在用于写入缓存的根名称和用于从缓存中读取的实体名称之间进行切换和更改.

继承下的缓存根本不起作用?我在想这个吗?

hai*_*Man 1

因此,为了解决这个问题,我必须修改 hibernate-core 中的 DefaultLoadEventListener,我将第 590 行更改为...

final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getRootEntityName()
);
Run Code Online (Sandbox Code Playgroud)

而不是...

final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getEntityName()
);
Run Code Online (Sandbox Code Playgroud)

因此基本上是使用超类名称而不是子类名称来查找对象。

休眠代码对我来说看起来是错误的,它是一个明显的修复,但我肯定做错了什么而不是发现错误?