一級緩存:java
會話session、事務級別的,事務退出,緩存就失效了。spring
實體管理器在事務執行期間持有一份數據的拷貝,而非直接操做數據源。數據庫
二級緩存:緩存
進程範圍級或集羣範圍的緩存,這個級別的緩存可配置和修改,整個應用程序的生命週期內均可以訪問。session
因爲多個事務會同時訪問二級緩存中相同的數據,所以二級緩存必須提供必要的併發訪問策略併發
以id爲標識放到緩存(針對id)ide
訪問過程:先一級緩存、後二級緩存,再數據源高併發
橋接第三方緩存,hibernate二級緩存的實現:fetch
1.ehcachethis
2.OScache
3.JBossCache
4.Memcached
......
什麼樣的數據適合二級緩存呢?
1.不多被修改的數據
2.不是很重要,容許偶爾出現併發的數據
3.不會被高併發訪問的數據
4.參數數據,一般是數量有限,極少被修改,大量的被其它實例引用的
不適合使用二級緩存?
1.常常被修改的數據,代價太大,得不償失
2.金錢敏感的數據,絕對不容許出現併發
3.與其餘應用共享的數據
查詢緩存:
批量的緩存、批量的獲取,如按查詢條件、查詢結果進行緩存;
JPA+Ehcache緩存配置:
1.加入Ehcache依賴
<!--Ehcache-core 包 --> <dependency> <groupId>net.sf.ehcache</groupId> <artifactId>ehcache-core</artifactId> <version>2.6.9</version> </dependency> <!--添加Hibernate-Ehcache包 --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-ehcache</artifactId> <version>${hibernate-version}</version> </dependency>
2.配置ehcache.xml
<?xml version="1.0" encoding="UTF-8"?> <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd"> <diskStore path="java.io.tmpdir/ehcache"/> <!-- 默認緩存 --> <defaultCache maxElementsInMemory="1000" <!-- 默認緩存中存最多數據項目 --> eternal="false" <!--是否永不過時--> timeToIdleSeconds="120" <!--空閒多長時間後從緩存中刪除--> timeToLiveSeconds="120" <!--活躍多長時間後從緩存中刪除--> overflowToDisk="false"/><!--超過maxElementsInMemory以後是否存儲到硬盤--> <!-- 題目緩存--> <cache name="questionCache" maxElementsInMemory="1000" eternal="true" timeToIdleSeconds="120" timeToLiveSeconds="120" overflowToDisk="false" memoryStoreEvictionPolicy="LRU" <!--數據項失效策略--> /> </ehcache>
3.persistence.xml配置加入緩存配置
entry key="hibernate.cache.use_second_level_cache" value="false" /><!--開啓二級緩存-->
<entry key="hibernate.cache.use_query_cache" value="false" /><!--開啓查詢緩存-->
<entry key="hibernate.cache.provider_class" value="org.hibernate.cache.EhCacheProvider"/> <!--ehcache支持-->
<entry key="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" /><!--ehcache支持-->
<entry key="hibernate.cache.provider_configuration" value="classpath:ehcache.xml"/><!--ehcache詳細配置-->
4.配置需二級緩存實體和屬性
在實體類和實體的那些集合屬性上啓用二級緩存使用
@Entity @Table(name = "user") @Cache(usage = CacheConcurrencyStrategy.READ_WRITE,region="指定的cache") @Cacheable(true) public class User implements java.io.Serializable { private static final long serialVersionUID = 6980093847795726310L; private String id; private String userName; private String password; private Set<Role> roles = new HashSet<Role>(); ....省略 /** *注:若是一個實體須要二級緩存,若該實體含有<set...>,<list...>等屬性時,也必需要指定緩存策略。 */ @ManyToMany(fetch = FetchType.LAZY) @Cache(usage = CacheConcurrencyStrategy.READ_WRITE) @JoinTable(name = "user_role", joinColumns = { @JoinColumn(name = "user_id", nullable = false, updatable = false) }, inverseJoinColumns = { @JoinColumn(name = "role_id", nullable = false, updatable = false) }) public Set<Role> getRoles() { return this.roles; } public void setRoles(Set<Role> roles) { this.roles = roles; } }
Usage提供緩存對象的事務隔離機制有以下幾種:
(NONE, READ_ONLY, NONSTRICT_READ_WRITE, READ_WRITE, TRANSACTIONAL)
ehcache不支持transaction事務機制,但其餘三種可使用:
read-only::
無需修改, 那麼就能夠對其進行只讀 緩存,注意,在此策略下,若是直接修改數據庫,即便可以看到前臺顯示效果,
可是將對象修改至cache中會報error,cache不會發生做用。另:刪除記錄會報錯,由於不能在read-only模式的對象從cache中刪除。
read-write:
須要更新數據,那麼使用讀/寫緩存 比較合適,前提:數據庫不能夠爲serializable transaction isolation level(序列化事務隔離級別)
nonstrice-read-write:
只偶爾須要更新數據(也就是說,兩個事務同時更新同一記錄的狀況很不常見),也不須要十分嚴格的事務隔離,那麼比較適合使用非嚴格讀/寫緩存策略。
5.配置查詢緩存
a.經過添加@QueryHints來實現查詢緩存
public interface DictDao extends JpaRepository<Dict, Integer>,JpaSpecificationExecutor<Dict>{ // spring-data-jpa默認繼承實現的一些方法,實現類爲SimpleJpaRepository。 // 該類中的方法不能經過@QueryHint來實現查詢緩存。 @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) List<Dict> findAll(); @Query("from Dict") @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) List<Dict> findAllCached(); @Query("select t from Dict t where t.name = ?1") @QueryHints({ @QueryHint(name = "org.hibernate.cacheable", value ="true") }) Dict findDictByName(String name); }
b.自定義Repository擴展接口內使用查詢緩存
public class UserReposiotryImpl { @PersistenceContext private EntityManager em; /** * 使用查詢緩存,調用setHint方法配置. */ public User findByCustomizeId() { return (User) em.createQuery("from User p where p.id=1") .setHint("org.hibernate.cacheable", true).getSingleResult(); }