当咱们使用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