Hibernate缓存不适用于子类

时间:2015-01-02 19:18:33

标签: java hibernate caching

Hibernate成功从缓存中检索查询结果, 然后它无法从缓存中检索实体,它为每一行执行了一个查询。

我调试了org.hibernate.event.internal.DefaultLoadEventListener,在我的情况下persister.hasNaturalIdentifier()返回了false,所以看起来实体永远不会被缓存。

我原以为ID应该用作默认的KEY。

protected Object doLoad(
            final LoadEvent event,
            final EntityPersister persister,
            final EntityKey keyToLoad,
            final LoadEventListener.LoadType options) {
        Object entity = loadFromSessionCache( event, keyToLoad, options );

        entity = loadFromSecondLevelCache( event, persister, options );
        if ( entity != null ) {
        }
        else {
            entity = loadFromDatasource( event, persister, keyToLoad, options );
        }    
        if ( entity != null && persister.hasNaturalIdentifier() ) { 
        event.getSession().getPersistenceContext().getNaturalIdHelper().cacheNaturalIdCrossReferenceFromLoad(
                    persister,
                    event.getEntityId(),
                    event.getSession().getPersistenceContext().getNaturalIdHelper().extractNaturalIdValues(
                            entity,
                            persister
                    )
            );
        }        
        return entity;
    }

之后

1 _ loadFromSecondLevelCache失败

2 _ 从Datasource加载

3 _ 然后它应该将实体放入缓存中,因为persister.hasNaturalIdentifier()返回false

如果我错了在加载后将实体插入缓存的hibernate序列在哪里?

经过一番搜索,我的问题正是这个secondlevelcache

它也是此coherence-hibernate-integration/1.0.0/secondlevelcache

的副本

所以真正的问题是

在创建cacheKey hibernate期间使用persister.getRootEntityName()

final CacheKey cacheKey = session.generateCacheKey( id, persister.getIdentifierType(), persister.getRootEntityName() );
    if ( session.getPersistenceContext().wasInsertedDuringTransaction( persister, id ) ) {
        persister.getCacheAccessStrategy().update(
                        cacheKey,
                        persister.getCacheEntryStructure().structure( entry ),
                        version,
                        version
                );
    }

但在回溯过程中使用persister.getEntityName() !!!!

protected Object loadFromSecondLevelCache(
            final LoadEvent event,
            final EntityPersister persister,
            final LoadEventListener.LoadType options) {

        final SessionImplementor source = event.getSession();
        final boolean useCache = persister.hasCache()
                && source.getCacheMode().isGetEnabled()
                && event.getLockMode().lessThan( LockMode.READ );

        if ( !useCache ) {
            // we can't use cache here
            return null;
        }

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

2 个答案:

答案 0 :(得分:0)

Hibernate按ID搜索缓存,而不是通过natural-id,检查此调用:

entity = loadFromSecondLevelCache( event, persister, options );

在您的情况下,可能是缓存条目因未决的并发实体修改而失效。

答案 1 :(得分:0)

更改 org.hibernate.engine.internal.TwoPhaseLoad

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

解决问题,但我愿意接受更好的解决方案