1. 程式人生 > >Hibernate 二級快取-ehcache

Hibernate 二級快取-ehcache

1 新增依賴包

<dependency>
   <groupId>junit</groupId>
   <artifactId>junit</artifactId>
   <version>4.12</version>
   <scope>test</scope>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>javax.servlet-api</artifactId>
   <version>3.1.0</version>
   <scope>provided</scope>
  </dependency>
  <dependency>
   <groupId>javax.servlet.jsp</groupId>
   <artifactId>javax.servlet.jsp-api</artifactId>
   <version>2.3.1</version>
  </dependency>
  <!-- pinyin4j jar -->
  <dependency>
   <groupId>com.belerweb</groupId>
   <artifactId>pinyin4j</artifactId>
   <version>2.5.0</version>
  </dependency>
  <!-- mysql驅動包 -->
  <dependency>
   <groupId>mysql</groupId>
   <artifactId>mysql-connector-java</artifactId>
   <version>5.1.44</version>
  </dependency>
  <!-- hibernate -->
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-core</artifactId>
   <version>5.3.6.Final</version>
  </dependency>
  <!-- struts2 jar包 -->
  <dependency>
   <groupId>org.apache.struts</groupId>
   <artifactId>struts2-core</artifactId>
   <version>2.5.14.1</version>
  </dependency>
  <!-- pinyin4j jar -->
  <dependency>
   <groupId>com.belerweb</groupId>
   <artifactId>pinyin4j</artifactId>
   <version>2.5.0</version>
  </dependency>
  <!-- jstl 依賴包 -->
  <dependency>
   <groupId>taglibs</groupId>
   <artifactId>standard</artifactId>
   <version>1.1.2</version>
  </dependency>
  <dependency>
   <groupId>javax.servlet</groupId>
   <artifactId>jstl</artifactId>
   <version>1.2</version>
  </dependency>
   <!-- 新增ehcache 和 hibernate-ehcache的 依賴包 -->
  <dependency>
   <groupId>net.sf.ehcache</groupId>
   <artifactId>ehcache</artifactId>
   <version>2.10.0</version>
  </dependency>
  <dependency>
   <groupId>org.hibernate</groupId>
   <artifactId>hibernate-ehcache</artifactId>
   <version>5.3.6.Final</version>
  </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">     <!--磁碟儲存:將快取中暫時不使用的物件,轉移到硬碟,類似於Windows系統的虛擬記憶體-->     <!--path:指定在硬碟上儲存物件的路徑-->     <!--java.io.tmpdir 是預設的臨時檔案路徑。 可以通過如下方式打印出具體的檔案路徑 System.out.println(System.getProperty("java.io.tmpdir"));-->     <diskStore path="java.io.tmpdir"/> 
    <!--defaultCache:預設的管理策略-->
    <!--eternal:設定快取的elements是否永遠不過期。如果為true,則快取的資料始終有效,如果為false那麼還要根據timeToIdleSeconds,timeToLiveSeconds判斷-->
    <!--maxElementsInMemory:在記憶體中快取的element的最大數目-->
    <!--overflowToDisk:如果記憶體中資料超過記憶體限制,是否要快取到磁碟上-->
    <!--diskPersistent:是否在磁碟上持久化。指重啟jvm後,資料是否有效。預設為false-->
    <!--timeToIdleSeconds:物件空閒時間(單位:秒),指物件在多長時間沒有被訪問就會失效。只對eternal為false的有效。預設值0,表示一直可以訪問-->
    <!--timeToLiveSeconds:物件存活時間(單位:秒),指物件從建立到失效所需要的時間。只對eternal為false的有效。預設值0,表示一直可以訪問-->
    <!--memoryStoreEvictionPolicy:快取的3 種清空策略-->
    <!--FIFO:first in first out (先進先出)-->
    <!--LFU:Less Frequently Used (最少使用).意思是一直以來最少被使用的。快取的元素有一個hit 屬性,hit 值最小的將會被清出快取-->
    <!--LRU:Least Recently Used(最近最少使用). (ehcache 預設值).快取的元素有一個時間戳,當快取容量滿了,而又需要騰出地方來快取新的元素的時候,那麼現有快取元素中時間戳離當前時間最遠的元素將被清出快取-->
    <defaultCache eternal="false" maxElementsInMemory="1000" overflowToDisk="false" diskPersistent="false"
                  timeToIdleSeconds="0" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU"/>
    <!--name: Cache的名稱,必須是唯一的(ehcache會把這個cache放到HashMap裡)-->
    <cache name="com.zking.hibernate.entity.Book" eternal="false" maxElementsInMemory="100"
           overflowToDisk="false" diskPersistent="false" timeToIdleSeconds="0"
           timeToLiveSeconds="300" memoryStoreEvictionPolicy="LRU"/>
</ehcache>

新增 log4j2.xml

<?xml version="1.0" encoding="UTF-8"?> <!-- status : 指定log4j本身的列印日誌的級別.ALL< Trace < DEBUG < INFO < WARN < ERROR 
 < FATAL < OFF。 monitorInterval : 用於指定log4j自動重新配置的監測間隔時間,單位是s,最小是5s. -->
<Configuration status="WARN" monitorInterval="30">
 <Properties>
  <!-- 配置日誌檔案輸出目錄 ${sys:user.home} -->
  <Property name="LOG_HOME">/root/workspace/lucenedemo/logs</Property>
  <property name="ERROR_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/error</property>
  <property name="WARN_LOG_FILE_NAME">/root/workspace/lucenedemo/logs/warn</property>
  <property name="PATTERN">%d{yyyy-MM-dd HH:mm:ss.SSS} [%t-%L] %-5level %logger{36} - %msg%n</property>
 </Properties> <Appenders>
  <!--這個輸出控制檯的配置 -->
  <Console name="Console" target="SYSTEM_OUT">
   <!-- 控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch) -->
   <ThresholdFilter level="trace" onMatch="ACCEPT"
    onMismatch="DENY" />
   <!-- 輸出日誌的格式 -->
   <!-- %d{yyyy-MM-dd HH:mm:ss, SSS} : 日誌生產時間 %p : 日誌輸出格式 %c : logger的名稱 
    %m : 日誌內容,即 logger.info("message") %n : 換行符 %C : Java類名 %L : 日誌輸出所在行數 %M 
    : 日誌輸出所在方法名 hostName : 本地機器名 hostAddress : 本地ip地址 -->
   <PatternLayout pattern="${PATTERN}" />
  </Console>  <!--檔案會打印出所有資訊,這個log每次執行程式會自動清空,由append屬性決定,這個也挺有用的,適合臨時測試用 -->
  <!--append為TRUE表示訊息增加到指定檔案中,false表示訊息覆蓋指定的檔案內容,預設值是true -->
  <File name="log" fileName="logs/test.log" append="false">
   <PatternLayout
    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
  </File>
  <!-- 這個會打印出所有的info及以下級別的資訊,每次大小超過size, 則這size大小的日誌會自動存入按年份-月份建立的資料夾下面並進行壓縮,作為存檔 -->
  <RollingFile name="RollingFileInfo" fileName="${LOG_HOME}/info.log"
   filePattern="${LOG_HOME}/$${date:yyyy-MM}/info-%d{yyyy-MM-dd}-%i.log">
   <!--控制檯只輸出level及以上級別的資訊(onMatch),其他的直接拒絕(onMismatch) -->
   <ThresholdFilter level="info" onMatch="ACCEPT"
    onMismatch="DENY" />
   <PatternLayout
    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
   <Policies>
    <!-- 基於時間的滾動策略,interval屬性用來指定多久滾動一次,預設是1 hour。 modulate=true用來調整時間:比如現在是早上3am,interval是4,那麼第一次滾動是在4am,接著是8am,12am...而不是7am. -->
    <!-- 關鍵點在於 filePattern後的日期格式,以及TimeBasedTriggeringPolicy的interval, 日期格式精確到哪一位,interval也精確到哪一個單位 -->
    <!-- log4j2的按天分日誌檔案 : info-%d{yyyy-MM-dd}-%i.log -->
    <TimeBasedTriggeringPolicy interval="1"
     modulate="true" />
    <!-- SizeBasedTriggeringPolicy:Policies子節點, 基於指定檔案大小的滾動策略,size屬性用來定義每個日誌檔案的大小. -->
    <!-- <SizeBasedTriggeringPolicy size="2 kB" /> -->
   </Policies>
  </RollingFile>  <RollingFile name="RollingFileWarn" fileName="${WARN_LOG_FILE_NAME}/warn.log"
   filePattern="${WARN_LOG_FILE_NAME}/$${date:yyyy-MM}/warn-%d{yyyy-MM-dd}-%i.log">
   <ThresholdFilter level="warn" onMatch="ACCEPT"
    onMismatch="DENY" />
   <PatternLayout
    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
   <Policies>
    <TimeBasedTriggeringPolicy />
    <SizeBasedTriggeringPolicy size="2 kB" />
   </Policies>
   <!-- DefaultRolloverStrategy屬性如不設定,則預設為最多同一資料夾下7個檔案,這裡設定了20 -->
   <DefaultRolloverStrategy max="20" />
  </RollingFile>  <RollingFile name="RollingFileError" fileName="${ERROR_LOG_FILE_NAME}/error.log"
   filePattern="${ERROR_LOG_FILE_NAME}/$${date:yyyy-MM}/error-%d{yyyy-MM-dd-HH-mm}-%i.log">
   <ThresholdFilter level="error" onMatch="ACCEPT"
    onMismatch="DENY" />
   <PatternLayout
    pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level %logger{36} - %msg%n" />
   <Policies>
    <!-- log4j2的按分鐘 分日誌檔案 : warn-%d{yyyy-MM-dd-HH-mm}-%i.log -->
    <TimeBasedTriggeringPolicy interval="1"
     modulate="true" />
    <!-- <SizeBasedTriggeringPolicy size="10 MB" /> -->
   </Policies>
  </RollingFile> </Appenders> <!--然後定義logger,只有定義了logger並引入的appender,appender才會生效 -->
 <Loggers>
  <!--過濾掉spring和mybatis的一些無用的DEBUG資訊 -->
  <logger name="org.springframework" level="INFO"></logger>
  <logger name="org.mybatis" level="INFO"></logger>  <!-- 第三方日誌系統 -->
  <logger name="org.springframework" level="ERROR" />
  <logger name="org.hibernate" level="ERROR" />
  <logger name="org.apache.struts2" level="ERROR" />
  <logger name="com.opensymphony.xwork2" level="ERROR" />
  <logger name="org.jboss" level="ERROR" />
  <!-- 配置日誌的根節點 -->
  <root level="all">
   <appender-ref ref="Console" />
   <appender-ref ref="RollingFileInfo" />
   <appender-ref ref="RollingFileWarn" />
   <appender-ref ref="RollingFileError" />
  </root> </Loggers></Configuration>

2:hibernate.cfg.xml中新增二級快取相關配置

<!-- 開啟二級快取 -->
  <property name="hibernate.cache.use_second_level_cache">true</property>
  <!-- 開啟查詢快取 -->
  <property name="hibernate.cache.use_query_cache">true</property>
  <!-- EhCache驅動 -->
  <property name="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.internal.EhcacheRegionFactory</property>

3:指定實體類開啟二級快取

    <!-- 註解式開發 -->    
   <class-cache usage="read-write" class="entity.Dict"/>   
       <!-- xml配置方式 -->
      <class name="com.zking.hibernate.entity.Book" table="t_hibernate_book">
       <cache usage="read-write" region="com.zking.hibernate.entity.Book"/>               
   .......
      </class>

4:在方法中開啟二級快取

public void testList11() {
  Query query = session.createQuery(" from Book");
      query.setCacheable(true);//手動開啟二級快取
  List<?> list = query.list();
  System.out.println(list.size());
  List<?> list1 = query.list();
  System.out.println(list1.size());
  List<?> list2 = query.list();
  System.out.println(list2.size());
 }

5:如果你沒有指定實體類開啟二級快取 可以手動繫結

query.setCacheRegion("entity.Dict");//指定快取策略,名字必須實體類的完整類名

演示結果: 演示結果