spring boot 2.1.4 hibernate 二級緩存 Caffeine實現

The Ehcache second-level cache provider for Hibernate is deprecated

當咱們使用hibernate-ehcache包(Ehcache 2)做爲hibernate二級緩存時,系統會提示警告說已通過時了,那這時候找到spring boot推薦的新的二級緩存方案,如今推薦hibernate-jcache,能夠與Ehcache 3或是其餘實現了javax.cache.spi.CachingProvider的緩存自動集成java

jcache是一種緩存門面規範,並不包含具體緩存實現,spring boot推薦與jcache搭配使用的是Hazelcast,Hazelcast實現了CachingProvider,能夠直接做爲hibernate二級緩存,Hazelcast實現下一篇再提供git

hibernate二級緩存重構以後,要本身實現也很是簡單,只須要實現github

org.hibernate.cache.spi.support.RegionFactoryTemplatespring

org.hibernate.cache.spi.support.DomainDataStorageAccessapache

這兩個類就能夠了,引入caffeine包緩存

<dependency>
	<groupId>com.github.ben-manes.caffeine</groupId>
	<artifactId>caffeine</artifactId>
</dependency>

下面是DomainDataStorageAccess實現,這個類就是緩存操做的實現springboot

import java.util.concurrent.TimeUnit;

import org.apache.commons.lang3.StringUtils;
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
import org.hibernate.engine.spi.SharedSessionContractImplementor;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;

import lombok.NonNull;

public class CaffeineDataRegion implements DomainDataStorageAccess {
	protected final Logger log = LoggerFactory.getLogger(this.getClass());
	/**
	 * Region regionName
	 */
	private final String regionName;
	private final Cache<Object, Object> cache;
	private final int expiryInSeconds; // seconds
	static final int DEFAULT_EXPIRY_IN_SECONDS = 1800;

	public CaffeineDataRegion(@NonNull String regionName) {
		this.regionName = StringUtils.replace(regionName, ".", ":") + ":";
		this.expiryInSeconds = DEFAULT_EXPIRY_IN_SECONDS;
		cache = Caffeine.newBuilder()
				// 設置cache中的數據在寫入以後的存活時間
				.expireAfterWrite(30, TimeUnit.MINUTES)
				// 構建cache實例
				.build();
		log.debug("caffeiene region={}, expiryInSeconds={}", regionName, expiryInSeconds);
	}

	/**
	 * confirm the specified key exists in current region
	 *
	 * @param key
	 *            cache key
	 * @return if cache key is exists in current region return true, else return
	 *         false
	 */
	@Override
	public boolean contains(Object key) {
		try {
			log.debug("contains key={}", key);
			return cache.getIfPresent(key) != null;
		} catch (Exception ignored) {
			log.warn("Fail to exists key. key=" + key, ignored);
			return false;
		}
	}

	@Override
	public Object getFromCache(Object key, SharedSessionContractImplementor session) {
		try {
			return cache.getIfPresent(key);
		} catch (Exception ignored) {
			log.warn("Fail to get cache item... key=" + key, ignored);
			return null;
		}
	}

	@Override
	public void putIntoCache(Object key, Object value, SharedSessionContractImplementor session) {
		try {
			cache.put(key, value);
		} catch (Exception ignored) {
			log.warn("Fail to put cache item... key=" + key, ignored);
		}
	}

	@Override
	public void evictData() {
		try {
			cache.invalidateAll();
		} catch (Exception ignored) {
			log.warn("Fail to clear region... name=" + regionName, ignored);
		}
	}

	@Override
	public void evictData(Object key) {
		try {
			cache.invalidate(key);
		} catch (Exception ignored) {
			log.warn("Fail to remove cache item... key=" + key, ignored);
		}
	}

	@Override
	public void release() {

	}
}

下面是RegionFactoryTemplate實現,這個類是緩存啓動類session

import java.util.Map;

import org.hibernate.boot.spi.SessionFactoryOptions;
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext;
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig;
import org.hibernate.cache.spi.support.DomainDataStorageAccess;
import org.hibernate.cache.spi.support.RegionFactoryTemplate;
import org.hibernate.cache.spi.support.StorageAccess;
import org.hibernate.engine.spi.SessionFactoryImplementor;

import com.bc.plugin.caffeine.hibernate.regions.CaffeineDataRegion;

import lombok.extern.slf4j.Slf4j;

@Slf4j
public class CaffeineRegionFactory extends RegionFactoryTemplate {
	private static final long serialVersionUID = 1L;

	@Override
	protected StorageAccess createQueryResultsRegionStorageAccess(String regionName,
			SessionFactoryImplementor sessionFactory) {
		return new CaffeineDataRegion(regionName);
	}

	@Override
	protected StorageAccess createTimestampsRegionStorageAccess(String regionName,
			SessionFactoryImplementor sessionFactory) {
		return new CaffeineDataRegion(regionName);
	}

	@Override
	protected DomainDataStorageAccess createDomainDataStorageAccess(DomainDataRegionConfig regionConfig,
			DomainDataRegionBuildingContext buildingContext) {
		return new CaffeineDataRegion(regionConfig.getRegionName());
	}

	@Override
	protected void prepareForUse(SessionFactoryOptions settings, @SuppressWarnings("rawtypes") Map configValues) {
		log.debug("RegionFactory is starting... options={}, properties={}", settings, configValues);
	}

	@Override
	protected void releaseFromUse() {

	}
}

 

而後配置spring.jpa.properties.hibernate.cache.region.factory_class=/*org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory  */ide

org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory是hibernate-ehcache包中的實現,ui

替換成咱們CaffeineRegionFactory類的全路徑就能夠了

引入caffeine包後,spring cache也會使用caffeine,springboot會自動配置caffeine

相關文章
相關標籤/搜索