Spring Data JPA 緩存結合Ehcache介紹


一級緩存:

會話session、事務級別的,事務退出,緩存就失效了。

實體管理器在事務執行期間持有一份數據的拷貝,而非直接操作數據源。

 

二級緩存:

進程范圍級或集群范圍的緩存,這個級別的緩存可配置和修改,整個應用程序的生命周期內都可以訪問。

由於多個事務會同時訪問二級緩存中相同的數據,因此二級緩存必須提供必要的並發訪問策略

以id為標識放到緩存(針對id)

訪問過程:先一級緩存、后二級緩存,再數據源

 

橋接第三方緩存,hibernate二級緩存的實現:

1.ehcache

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();        
    }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM