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