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