JPA 缓存


对于JPA2.0,缓存分为一级缓存和二级缓存(JPA1.0只支持一级缓存)。二级缓存通常是用来提高应用程序性能的,它可以避免访问以已经从数据库加载的数据,提高访问未被修改数据对象的速度。

持久化上下文就是JPA的一级缓存,通过在持久化上下文中存储持久化状态实体的快照,既可以进行脏检测,还可以当做持久化实体的缓存。一级缓存属于请求范围级别的缓存,如下


JPA二级缓存是跨越持久化上下文的,是真正意义上的全局应用缓存,如下


如果二级缓存激活,JPA会先从一级缓存中寻找实体,未找到再从二级缓存中寻找。当二级缓存有效时,就不能依靠事务来保护并发的数据,而是依靠锁策略,如在确认修改后,需要手工处理乐观锁失败等。

注意:二级缓存只能缓存通过EntityManagerfindgetReference查询到的实体,以及通过实体的getter方法获取到的关联实体;而不能缓存通过JPQL查询获得的数据。

二级缓存通常用来提高性能,同时,使用二级缓存可能会导致提取到“陈旧”数据,也会出现并发写的问题。所以二级缓存最好是用在经常阅读数据,比较少更新数据的情况,而不应该对重要数据使用二级缓存。

对于不同的JPA实现产品,开启二级缓存的方式会有所不同,下面以 Spring+Hibernate为例,开启二级缓存,步骤如下

1)     添加hibernate-ehcache.jar文件,推荐使用maven来管理;

2)     修改Spring配置文件,开启二级缓存

3)     将需要缓存的实体类标注@ javax.persistence.Cacheableorg.hibernate.annotations.Cache

1、@Cacheable配置

采用@javax.persistence.Cacheable配置,开启二级缓存如下

<!--jpa-->

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="dataSource" ref="dataSource"/>

        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>

        <property name="persistenceUnitName" value="template"/>

        <property name="packagesToScan" value="org.ssl.template.model"/>

        <!---指定JPA适配器-->

        <property name="jpaVendorAdapter">

              <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

                    <property name="showSql" value="true" />

                    <property name="generateDdl" value="true"/>

              </bean>

        </property>

        <propertyname="jpaProperties"> 

            <props>

            <propkey="hibernate.cache.use_second_level_cache">true</prop>  

                <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

                <!--设置sharedCache.modeENABLE_SELECTIVE时,在实体上添加@Cacheable就可以被缓存--> 

                <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>

                 <!--输出统计信息,在部署时需要关闭--> 

                <prop key="hibernate.generate_statistics">true</prop> 

            </props> 

        </property> 

</bean>

 

注意:

u 实体上标注@cacheable时,需要设置javax.persistence.sharedCache.mode属性值;

u javax.persistence.sharedCache.mode

值可以为ENABLE_SELECTIVE(推荐值)、DISABLE_SELECTIVE、NONE、ALL;

若为ENABLE_SELECTIVE,则只要添加@Cacheable注解的实体才会被缓存;

若为DISABLE_SELECTIVE,则标注@Cacheable(value=false)的实体才被缓存;

若为NONE,任何实体都不会被缓存,即使被@Cacheable标注;

若为ALL,实体都会被缓存,即使没有@Cacheable标注;

u 开启Hibernate的查询缓存

除了设置

key="hibernate.cache.use_query_cache">true</prop> 

外,还需要在JPA查询时采用@QueryHint来实现查询缓存,如下

public interface DictDao

{

   // 通过@QueryHint来实现查询缓存。

   @QueryHints({@QueryHint(name = "org.hibernate.cacheable", value ="true")})

   List<Dict>findAll();

}

2、@Cache配置

采用org.hibernate.annotation.Cache配置时,设置如下:

<!--jpa-->

<bean id="entityManagerFactory" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">

        <property name="dataSource" ref="dataSource"/>

        <property name="persistenceXmlLocation" value="classpath:META-INF/persistence.xml"/>

        <property name="persistenceUnitName" value="template"/>

        <property name="packagesToScan" value="org.ssl.template.model"/>

        <!---指定JPA适配器-->

        <property name="jpaVendorAdapter">

              <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">

                    <property name="showSql" value="true" />

                    <property name="generateDdl" value="true"/>

              </bean>

        </property>

        <propertyname="jpaProperties"> 

            <props>

            <propkey="hibernate.cache.use_second_level_cache">true</prop>  

               <propkey="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>

                <!--输出统计信息,在部署时需要关闭--> 

                <prop key="hibernate.generate_statistics">true</prop> 

            </props> 

        </property> 

</bean>

采用@cache时,除了在实体上标注@Cache外,还需要添加ehcache.xml配置文件,如下

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"

        xsi:noNamespaceSchemaLocation="ehcache.xsd">

    <defaultCache

            maxElementsInMemory="1000"

            eternal="false"

            timeToIdleSeconds="120"

            timeToLiveSeconds="180"

            overflowToDisk="false"

           memoryStoreEvictionPolicy="LRU"

            />

           

    <cache name="org.hibernate.cache.internal.StandardQueryCache"

       maxElementsInMemory="100"

       eternal="false"

       timeToIdleSeconds="120"

        timeToLiveSeconds="180"

       overflowToDisk="true" />

 

    <cache name="org.hibernate.cache.spi.UpdateTimestampsCache"

       maxElementsInMemory="100"

       eternal="false"

       timeToIdleSeconds="120"

        timeToLiveSeconds="180"

       overflowToDisk="false" />

 

      

    <!--单个实体的缓存设置,不设置采用默认设置-->

    <!--

    <cachename="org.ssl.template.model.Template"

          maxElementsInMemory="100"

           eternal="false"

          timeToIdleSeconds="120"

          timeToLiveSeconds="180"

          overflowToDisk="false"

          memoryStoreEvictionPolicy="LRU"

            />

     -->

</ehcache>

 

注意:

u Hibernate3.x与Hibernate4.x开启二级缓存设置不同

Hibernate4.x:

<propkey="hibernate.cache.region.factory_class">

org.hibernate.cache.ehcache.EhCacheRegionFactory

</prop>

Hibernate3.x:

<prop key="hibernate.cache.provider_class ">

org.hibernate.cache.EhCacheProvider

</prop>

u 在部署项目时,需要将调试信息关闭,如关闭显示sql语句、关闭更新数据表、更改日志的输出级别等。

阅读更多
想对作者说点什么?

博主推荐

换一批

没有更多推荐了,返回首页