JPA缓存

1.概述

   对于JPA2.0,缓存分为一级缓存和二级缓存(JPA1.0只支持一级缓存)。

   二级缓存通常是用来提高应用程序性能的,它可以避免访问以已经从数据库加载的数据,提高访问未被修改数据对象的速度

   持久化上下文就是JPA的一级缓存,通过在持久化上下文中存储持久化状态实体的快照,既可以进行脏检测

   还可以当做持久化实体的缓存。一级缓存属于请求范围级别的缓存,如下

   

 

   注:一级缓存只是一个实体对象的持久化

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

    

 

    注:

      第一点:如果二级缓存激活,JPA会先从一级缓存中寻找实体,未找到再从二级缓存中寻找。

                    当二级缓存有效时,就不能依靠事务来保护并发的数据,而是依靠锁策略,如在确认修改后,需要手工处理乐观锁失败等。

      第二点:二级缓存只能缓存通过EntityManager的find或getReference查询到的实体

                    以及通过实体的getter方法获取到的关联实体;而不能缓存通过JPQL查询获得的数据。--也就是说缓存是通过容器的方式

     第三点:二级缓存通常用来提高性能,同时,使用二级缓存可能会导致提取到“陈旧”数据,

                   也会出现并发写的问题。所以二级缓存最好是用在经常阅读数据,比较少更新数据的情况,而不应该对重要数据使用二级缓存。

    

 

2.开启二级缓存(对于不同的JPA实现产品,开启二级缓存的方式会有所不同)

   Spring+Hibernate(最常用的)

        第一步:添加hibernate-ehcache.jar文件,推荐使用maven来管理;

        第二步:修改Spring配置文件,开启二级缓存

        第三步:将需要缓存的实体类标注@ javax.persistence.Cacheable或org.hibernate.annotations.Cache。

          第一种 :@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>
        <property name="jpaProperties">
             <props>
                   <prop key="hibernate.cache.use_second_level_cache">true</prop> 
                  <prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.EhCacheRegionFactory</prop>
                  <!--设置sharedCache.mode为ENABLE_SELECTIVE时,在实体上添加@Cacheable就可以被缓存-->
                  <prop key="javax.persistence.sharedCache.mode">ENABLE_SELECTIVE</prop>
                  <!--输出统计信息,在部署时需要关闭-->
                  <prop key="hibernate.generate_statistics">true</prop>
            </props>
        </property> 
    </bean>

    总结:

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

       第二点:javax.persistence.sharedCache.mode值可以为ENABLE_SELECTIVE(推荐值)、DISABLE_SELECTIVE、NONE、ALL;

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

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

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

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

       第三点:开启Hibernate的查询缓存

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

             2.需要在JPA查询时采用@QueryHint来实现查询缓存

                public interface DictDao {

                     // 通过@QueryHint来实现查询缓存。
                    @QueryHints({@QueryHint(name = "org.hibernate.cacheable", value ="true")})
                     List<Dict>findAll();
                }

       

      第二种:@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>
          <property name="jpaProperties">
              <props>
               <prop key="hibernate.cache.use_second_level_cache">true</prop> <!--propkey 合并和分开是否都行可以尝试下--> 
                  <prop key="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>

   总结:

      第一点: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>

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

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

 

学习来源:https://blog.csdn.net/sunshuolei/article/details/48065955

   

posted @ 2020-09-10 10:58  小窝蜗  阅读(1651)  评论(0编辑  收藏  举报