spring boot 2.0.1.RELEASE hibernate 緩存 ehcache 詳解

啓用hibernate 緩存application.yml配置:java

spring:
  jpa:    
    properties:
      javax:
        persistence:
          sharedCache:
            mode: ENABLE_SELECTIVE
      hibernate:
        cache:
          use_query_cache: true
          use_second_level_cache: true
          region:
            factory_class: org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory

sharedCacheModel:git

    ENABLE_SELECTIVE,默認值,除非被@Cacheable顯式聲明要緩存,不然默認不緩存github

    DISABLE_SELECTIVE,除非被@Cacheable顯式聲明不緩存,不然默認緩存spring

    ALL,老是被緩存sql

    NONE,老是不緩存數據庫

 

hibernate實現中只有三種緩存類型: 緩存

一級緩存:默認啓用,沒法關閉,session級別, 同一個session內部,一級緩存生效,同一個id的對象只有一個。不一樣session,一級緩存無效session

二級緩存:  sessionFactory級別,使用方式有兩種:第一種不使用hibernate的@cache標記,直接在實體上用@cacheable(javax.persistence.Cacheable)標記而且要配置緩存配置項: javax.persistence.sharedCache.mode:ENABLE_SELECTIVE, 第二種用hibernate的@cache標記使用,app

一、二級緩存針對列表數據默認只緩存id,再經過id從數據庫中查找less

二、二級緩存緩存的僅僅是對象,若是查詢出來的是對象的一些屬性,則不會被加到緩存中去

三、 只有當 HQL 查詢語句徹底相同時,連參數設置都要相同,此時查詢緩存纔有效

 

查詢緩存: 使用方式 queryImpl.setCacheable(true);必須設置纔會生效

查詢緩存緩存的也僅僅是對象的id,因此第一條 sql 也是將對象的id都查詢出來,可是當咱們後面若是要獲得每一個對象的信息的時候,此時又會發sql語句去查詢,因此,若是要使用查詢緩存,咱們必定也要開啓咱們的二級緩存,這樣就不會出現 N+1 問題了

 

private void setHibernateQuery(Query query) {
          if (query instanceof QueryImpl) {
              QueryImpl<?> queryImpl = (QueryImpl<?>)  query;
              queryImpl.setCacheable(true);
          }
     }

ehcache.xml配置文件:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache name="HIBERNATE_CACHE"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     xsi:noNamespaceSchemaLocation="http://www.ehcache.org/ehcache.xsd"
     updateCheck="true" monitoring="autodetect"  dynamicConfig="true">
     <!-- 指定二級緩存存放在磁盤上的位置,可使用磁盤目錄,也可使用Java System Property目錄,user.home是用戶目錄、user.dir是用戶當前工做目錄、java.io.tmpdir是默認臨時文件路徑  -->
     <diskStore path="target/cache/hibernate" />
     <transactionManagerLookup
          class="net.sf.ehcache.transaction.manager.DefaultTransactionManagerLookup"
          properties="jndiName=java:/TransactionManager"  propertySeparator=";" />
     <defaultCache maxEntriesLocalHeap="0"  eternal="false" diskPersistent="false"
          timeToIdleSeconds="3600" timeToLiveSeconds="0">
          <!--<terracotta/> -->
     </defaultCache>
     <!--能夠給每一個實體類指定一個配置文件,經過name屬性指定,要使用類的全名
          1. name:Cache的惟一標識。
          2. maxElementsInMemory:內存中最大緩存對象數。
          3. eternal:Element是否永久有效,一旦設置true,timeout將不起做用。
          4. timeToIdleSeconds:設置Element在失效前的容許閒置時間。僅當element不是永久有效時使用,可選屬性,默認值是0,也就是可閒置時間無窮大。
          5. timeToLiveSeconds:設置Element在失效前容許存活時間。最大時間介於建立時間和失效時間之間。僅當element不是永久有效時使用,默認是0.,也就是element存活時間無窮大。
          6. overflowToDisk:配置此屬性,當內存中Element數量達到maxElementsInMemory時,Ehcache將會Element寫到磁盤中。
          7. maxElementsOnDisk:磁盤中最大緩存對象數,如果0表示無窮大。
          8. memoryStoreEvictionPolicy:當達到maxElementsInMemory限制時,Ehcache將會根據指定的策略去清理緩存中的內容。默認策略是LRU(最近最少使用),你也能夠設置爲FIFO(先進先出)或是LFU(較少使用)
          9. diskSpoolBufferSizeMB : 這個參數設置DiskStore(磁盤緩存)的緩存區大小。默認是30MB。每一個Cache都應該有本身的一個緩衝區
          10. maxEntriesLocalHeap堆內存中最大緩存對象數,0沒有限制(必須設置)
          11. maxEntriesLocalDisk硬盤最大緩存個數 -->
          
     <cache  name="org.hibernate.cache.internal.StandardQueryCache"
          maxEntriesLocalHeap="0" eternal="false"  timeToIdleSeconds="1200">
          <persistence strategy="localTempSwap" />
     </cache>
     <cache  name="org.hibernate.cache.spi.UpdateTimestampsCache"
          maxEntriesLocalHeap="5000" eternal="true">
          <persistence strategy="localTempSwap" />
     </cache>
</ehcache>

org.springframework.cache.annotation.Cacheable註解使用異常問題:

java.lang.IllegalArgumentException: Cannot find cache named '緩存名' for Builder[加了cacheable註解的方法名] caches=[緩存名] | key='#groupName' | keyGenerator='' | cacheManager='' | cacheResolver='' | condition='' | unless='' | sync='false'

@Cacheable(value = "findByGroup", key =  "#groupName")

若是findByGroup未在ehcache.xml中配置,會出現沒法找到緩存名的異常,可使用CaffeineCacheManager或其餘的緩存組件做爲應用層緩存替換掉EhCacheCacheManager,就能夠不用配置緩存名了,數據庫緩存仍是使用的ehcache,不會產生影響

@EnableCaching
@Configuration
public class BcCacheManagerConfig {
     @Bean
     @ConditionalOnMissingBean(CacheManager.class)
     public CaffeineCacheManager caffeineCacheManager() {
          return new CaffeineCacheManager();
     }
}

相關包引入

<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>2.0.1.RELEASE</version>
	</parent>     
----------------------------------------------------------------------------

   <dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-cache</artifactId>
		</dependency>
		<!-- https://mvnrepository.com/artifact/com.github.ben-manes.caffeine/caffeine -->
		<dependency>
			<groupId>com.github.ben-manes.caffeine</groupId>
			<artifactId>caffeine</artifactId>
		</dependency>
        <!-- 集成ehcache須要的依賴 -->
		<dependency>
			<groupId>org.hibernate</groupId>
			<artifactId>hibernate-ehcache</artifactId>
			<exclusions>
		        <exclusion>
		            <groupId>net.sf.ehcache</groupId>
		            <artifactId>ehcache-core</artifactId>
		        </exclusion>
		    </exclusions>
		</dependency>
相關文章
相關標籤/搜索