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

相关文章
相关标签/搜索