java - hibernate 继承缓存,CacheKey 中使用的实体名称不正确?

标签 java hibernate caching inheritance ehcache

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

但它似乎在 TABLE_PER_CLASS 继承模型中被打破,对于缓存键中的实体名称似乎存在一些混淆,对象作为父类(super class)名称保存到区域中但是当它去检索对象时它正在使用子类名称。

所以我有 2 个类,一个 super 类和一个子类...

@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;

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

该区域将如预期的那样是父类(super class)名称。第一次加载运行时,它会将对象放入二级缓存中,我可以通过运行以下代码的统计信息来查看它

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

if( cacheEntries.size() > 0 ){
    System.out.println( "  ...  " + cacheEntries ) ;        
}

打印出...

   - com.core.dao.GroupLinkEntity
  ...  {1=CacheEntry(com.core.dao.Node)[........

所以我知道 PK 为 1 的 Node 对象就在那里。

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

com.core.dao.Node#1

但是如果我查看区域中的缓存对象,我可以看到它保存的键是...

[com.core.dao.GroupLinkEntity#1]

我知道它们都是同一个对象,但是写入和读取之间的某些东西出了问题。

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

final CacheKey cacheKey = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );

但是他们使用类名创建缓存键以在 DefaultLoadEventListener 中检索...

final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getEntityName()
);

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

继承下的缓 stub 本不起作用?这是我的想象吗?

最佳答案

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

final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getRootEntityName()
);

而不是...

final SessionFactoryImplementor factory = source.getFactory();
final CacheKey ck = source.generateCacheKey(
        event.getEntityId(),
        persister.getIdentifierType(),
        persister.getEntityName()
);

所以基本上是使用父类(super class)名称而不是子类名称找到对象。

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

关于java - hibernate 继承缓存,CacheKey 中使用的实体名称不正确?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23300935/

相关文章:

java - java.util.Collection 为什么不实现新的 Stream 接口(interface)?

java - Tomcat 7 TagLib 和用户问题

java - JPA 实体是否应该为 hashcode() 实现返回一个常量?

java - HQL 查询在运行 SQL 查询时抛出 QueryException

PHP URL 字符串以避免浏览器缓存

javascript - 使用 ServiceWorker 的永久浏览器缓存

java - Android - xml & 符号转换

Java VisualVM 无​​法连接到 Jboss

java - 从嵌入 Hibernate 的 H2 加载 BLOB 表

C++ 设置使用线性探测?