spring-boot+mybatis+ehcache實現快速查詢


項目中需要用到一些查詢,數據的修改很少但查詢度很大。有時還是按頻率查詢的。

 無論如何緩存都是針對查詢遠遠大於更新和插入的情況

mybatis 有自帶的緩存,一級緩存是session級別,二級緩存是namespace 。

開啟二級緩的缺點:1)只有在一個namespace操作單表時使用,比如:user,和user_role兩張表,如果user_role修改了,利用user的namespace去查詢的結果就是臟數據。

         2)在更新其中一條的時候,整個namespace都會被刷新。我們其實知道只要刷新一條就好。

個人覺得業務層自己控制會比較好。

我目前項目中遇到2種情況,

1)業務只查詢最近半小時的數據,數據時常更新,不斷會有數據插入。就是一些臨時的性能數據。

方案:給個ehcache,保存最近半小時的數據,設置定時任務,把之前的數據批量入庫。查詢優先在緩存中進行。

2)數據庫的數據是配置型的,比如用戶的個人信息,然后多個地方需要用到。並且用到的頻率都很大。

方案:業務層使用ehcache和mybatis 緩存。當然,你也可以單獨寫一個ehcache緩存類來操作這個緩存。然后隨着業務的增大,感覺好多表的數據都需要這類緩存的時候,你就開始思考人生了。

 

單獨寫ehcache類,保存數據。

spring-boot +mybaits +ehcache (緩存注解,你想放哪里就哪里。如果考慮到會直接修改數據庫,寫個后門,直接刷新緩存,注意安全!)

maven構建。

關鍵依賴的包(具體版本按最新的來)

    <dependency>
            <groupId>org.springframework</groupId>
            <artifactId>spring-context-support</artifactId>
        </dependency>
      <dependency>
        <groupId>net.sf.ehcache</groupId>
        <artifactId>ehcache</artifactId>
    </dependency>        

 

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" updateCheck="false">
    <diskStore path="user.dir/sqlEhCache" />
    
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" />

    <cache name="baseCache" eternal="true" maxElementsInMemory="1000" maxElementsOnDisk="10000" overflowToDisk="true" diskPersistent="false" timeToIdleSeconds="0" timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU" />

</ehcache>

 

 

(1).diskStore: 為緩存路徑,ehcache分為內存和磁盤兩級,此屬性定義磁盤的緩存位置。參數解釋如下:    
             user.home – 用戶主目錄
             user.dir  – 用戶當前工作目錄
             java.io.tmpdir – 默認臨時文件路徑

  (2).defaultCache:默認緩存策略,當ehcache找不到定義的緩存時,則使用這個緩存策略。只能定義一個。

       (3).cache:自定緩存策略,為自定義的緩存策略。參數解釋如下:

cache元素解釋:

cache元素的屬性:

name:緩存名稱

maxElementsInMemory:內存中最大緩存對象數

maxElementsOnDisk:硬盤中最大緩存對象數,若是0表示無窮大

eternal:true表示對象永不過期,此時會忽略timeToIdleSeconds和timeToLiveSeconds屬性,默認為false

overflowToDisk:true表示當內存緩存的對象數目達到了

maxElementsInMemory界限后,會把溢出的對象寫到硬盤緩存中。注意:如果緩存的對象要寫入到硬盤中的話,則該對象必須實現了Serializable接口才行。

diskSpoolBufferSizeMB:磁盤緩存區大小,默認為30MB。每個Cache都應該有自己的一個緩存區。

diskPersistent:是否緩存虛擬機重啟期數據,是否持久化磁盤緩存,當這個屬性的值為true時,系統在初始化時會在磁盤中查找文件名 為cache名稱,后綴名為index的文件,這個文件中存放了已經持久化在磁盤中的cache的index,找到后會把cache加載到內存,要想把 cache真正持久化到磁盤,寫程序時注意執行net.sf.ehcache.Cache.put(Element element)后要調用flush()方法。

diskExpiryThreadIntervalSeconds:磁盤失效線程運行時間間隔,默認為120秒

timeToIdleSeconds: 設定允許對象處於空閑狀態的最長時間,以秒為單位。當對象自從最近一次被訪問后,如果處於空閑狀態的時間超過了timeToIdleSeconds屬性 值,這個對象就會過期,EHCache將把它從緩存中清空。只有當eternal屬性為false,該屬性才有效。如果該屬性值為0,則表示對象可以無限 期地處於空閑狀態

timeToLiveSeconds:設定對象允許存在於緩存中的最長時間,以秒為單位。當對象自從被存放到緩存中后,如果處於緩存中的時間超過了 timeToLiveSeconds屬性值,這個對象就會過期,EHCache將把它從緩存中清除。只有當eternal屬性為false,該屬性才有 效。如果該屬性值為0,則表示對象可以無限期地存在於緩存中。timeToLiveSeconds必須大於timeToIdleSeconds屬性,才有 意義

memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理內存。可選策略有:LRU(最近最少使用,默認策略)、FIFO(先進先出)、LFU(最少訪問次數)。

spring-boot注入,該java代碼主要是根據配置生成cache

package com.configure; import org.springframework.cache.annotation.EnableCaching; import org.springframework.cache.ehcache.EhCacheCacheManager; import org.springframework.cache.ehcache.EhCacheManagerFactoryBean; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.io.ClassPathResource; @Configuration //標注啟動了緩存
@EnableCaching public class CacheConfiguration { /* * ehcache 主要的管理器 */ @Bean(name = "appEhCacheCacheManager") public EhCacheCacheManager ehCacheCacheManager(EhCacheManagerFactoryBean bean){ return new EhCacheCacheManager (bean.getObject ()); } /* * 據shared與否的設置,Spring分別通過CacheManager.create()或new CacheManager()方式來創建一個ehcache基地. */ @Bean public EhCacheManagerFactoryBean ehCacheManagerFactoryBean(){ EhCacheManagerFactoryBean cacheManagerFactoryBean = new EhCacheManagerFactoryBean (); cacheManagerFactoryBean.setConfigLocation (new ClassPathResource ("ehcache.xml")); cacheManagerFactoryBean.setShared (true); return cacheManagerFactoryBean; } }

 

之后利用注解,可以在你想要的地方利用緩存,注意如果有緩存了,就不會走原來的方法。

public interface TransformerDao { /** *刪除該value下的所有緩存,整個都刷新 * @param stationOid * @return
     */ @Caching(evict={@CacheEvict(value="baseCache",allEntries=true)}) public int deleteByStationOid(@Param("stationOid") String stationOid); /** * 查詢該充電樁所屬變壓群(器)信息 * * @param pileOid * @return
     */ @Cacheable(value="baseCache", key = "#p0") public Transformer queryTransformerByPileOid( @Param("pileOid") String pileOid); }

關於@Cacheable、@CachePut和@CacheEvict介紹,參考:

http://blog.csdn.net/u014381863/article/details/48788199

有一個坑,就是不能直接使用 參數名作為key

只能使用  #p 這種模式

具體原因參考:

https://stackoverflow.com/questions/14197359/spring-cache-abstraction-vs-interfaces-vs-key-param-null-key-returned-for-cach

 


免責聲明!

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



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