java编程

hibernate的查询缓存使用

字号+ 作者:zhuawa 来源:未知 2016-06-17 14:57 我要评论( )

从源码上分析hibernate的缓存的使用

Hibernate 查询List缓存的使用,从源码看出,首先必须hibernate属性必须是queryCacheEnabled=true,然后查询参数    query.setCacheable(true); 他就会从查询缓存里面找

protected List list(
            final SessionImplementor session,
            final QueryParameters queryParameters,
            final Set querySpaces,
            final Type[] resultTypes) throws HibernateException {

        final boolean cacheable = factory.getSettings().isQueryCacheEnabled() &&
            queryParameters.isCacheable();

        if ( cacheable ) {
            return listUsingQueryCache( session, queryParameters, querySpaces, resultTypes );
        }
        else {
            return listIgnoreQueryCache( session, queryParameters );
        }
    }

Hibernate 查询get缓存的使用
protected Object doLoad(
        ……

        Object entity = loadFromSessionCache( event, keyToLoad, options );
        ……

        entity = loadFromSecondLevelCache(event, persister, options);
        if ( entity != null ) {
            if ( traceEnabled ) LOG.tracev( "Resolved object in second-level cache: {0}",
                    MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) );
        }
        else {
            if ( traceEnabled ) LOG.tracev( "Object not resolved in any cache: {0}",
                    MessageHelper.infoString( persister, event.getEntityId(), event.getSession().getFactory() ) );
            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;
    }
这个是hibernate 使用get或者load的时候会调用的代码,在调用的时候先从session缓存中找,然后再loadFromSecondLevelCache 找,当然session中找到了他就不会去找了。
下面是loadFromSecondLevelCache中的代码
    protected Object loadFromSecondLevelCache(
        ……
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.getRootEntityName()
        );

        final Object ce = CacheHelper.fromSharedCache( source, ck, persister.getCacheAccessStrategy() );
        if ( factory.getStatistics().isStatisticsEnabled() ) {
            if ( ce == null ) {
                factory.getStatisticsImplementor().secondLevelCacheMiss(
                        persister.getCacheAccessStrategy().getRegion().getName()
                );
            }
            else {
                factory.getStatisticsImplementor().secondLevelCacheHit(
                        persister.getCacheAccessStrategy().getRegion().getName()
                );
            }
        }

        if ( ce == null ) {
            // nothing was found in cache
            return null;
        }

        CacheEntry entry = (CacheEntry) persister.getCacheEntryStructure().destructure( ce, factory );
        return convertCacheEntryToEntity( entry, event.getEntityId(), persister, event );
    }
这段代码说的是首先看看是否启用缓存了,如果没启用就返回空,如果启用了,根据source信息封装成一个key,通过工具类没有找到就返回null,如果找到了,就作一些操作返回一个entity

配置:中间粗体就是配置hibernate的缓存的,使用的是ehcache,如果要在在查找列表的时候注意要在查询参数中加入    query.setCacheable(true); 才会从缓存里面找
<!-- 配置hibernate session工厂 -->
    <bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
        <property name="dataSource" ref="dataSource" />
        <property name="hibernateProperties">
            <props>
                <!-- spring中如果想通过sessionFactory.getCurrentSession获得当前session,必须配置sessionFactory和thread绑定。 -->
                <!--  prop key="hibernate.connection.autocommit">${hibernate.autocommit}</prop> -->
                <prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</prop>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
                <prop key="hibernate.show_sql">${hibernate.show_sql}</prop>
                <prop key="hibernate.format_sql">${hibernate.format_sql}</prop>
                <!-- cache start -->
                <prop key="hibernate.cache.use_minimal_puts">true</prop>
                <prop key="hibernate.cache.use_second_level_cache">true</prop>
                <prop key="hibernate.cache.use_query_cache">true</prop>
                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

                 <!-- cache end-->
            </props>
        </property>

        <property name="mappingLocations">    
            <value>classpath:/hand/framework/model/*.hbm.xml </value>    
        </property>
        <!-- 自动扫描注解方式配置的hibernate类文件 -->
        
        <property name="packagesToScan">
            <list>
                <value>hand.framework.model</value>
            </list>
        </property>
        
        <!-- 自动扫描hbm方式配置的hibernate文件和.hbm文件 -->
        <!--
        <property name="mappingDirectoryLocations">
            <list>
                <value>classpath:/hand/framework/model</value>
            </list>
        </property>
         -->
    </bean>

转载请注明出处。

1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,请转载时务必注明文章作者和来源,不尊重原创的行为我们将追究责任;3.作者投稿可能会经我们编辑修改或补充。

相关文章
  •  为什么一些大型项目不使用Hibernate框架

    为什么一些大型项目不使用Hibernate框架

    2016-01-10 12:54

网友点评
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)