Spring Data JPA 緩存結合Ehcache介紹

一級緩存: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();        
    }
相關文章
相關標籤/搜索