适合使用集群服务
效果:
创建rest-api-plugin插件,目录结构
1、实现 RegionFactoryTemplate 类
package middolhibernaterediscache
import grails.plugins.redis.RedisService
import grails.util.Holders
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.hibernate.boot.spi.SessionFactoryOptions
import org.hibernate.cache.CacheException
import org.hibernate.cache.cfg.spi.DomainDataRegionBuildingContext
import org.hibernate.cache.cfg.spi.DomainDataRegionConfig
import org.hibernate.cache.internal.DefaultCacheKeysFactory
import org.hibernate.cache.spi.CacheKeysFactory
import org.hibernate.cache.spi.DomainDataRegion
import org.hibernate.cache.spi.SecondLevelCacheLogger
import org.hibernate.cache.spi.support.*
import org.hibernate.engine.spi.SessionFactoryImplementor
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.stereotype.Component
import redis.clients.jedis.Jedis
/**
* @Description: 自定义hibernate 二级缓存 使用jedis
* @Author: zhangjiayu@middol.com
* @CreateDate: 2020/7/31 10:55
* @Version: 1.0
*/
@Slf4j
@CompileStatic
class RedisRegionFactory extends RegionFactoryTemplate {
private static final long serialVersionUID = 1L
private final CacheKeysFactory cacheKeysFactory
protected volatile RedisClient redisClient
RedisService redisService = Holders.grailsApplication.mainContext.getBean(RedisService.class)
RedisRegionFactory() {
this(DefaultCacheKeysFactory.INSTANCE)
}
RedisRegionFactory(CacheKeysFactory cacheKeysFactory) {
this.cacheKeysFactory = cacheKeysFactory
}
@Override
protected CacheKeysFactory getImplicitCacheKeysFactory() {
return cacheKeysFactory
}
@Override
DomainDataRegion buildDomainDataRegion(DomainDataRegionConfig regionConfig,
DomainDataRegionBuildingContext buildingContext) {
return new DomainDataRegionImpl(regionConfig, this, createDomainDataStorageAccess(regionConfig, buildingContext),
cacheKeysFactory, buildingContext)
}
/**
* 创建实体缓存
* @param regionConfig
* @param buildingContext
* @return
*/
@Override
protected DomainDataStorageAccess createDomainDataStorageAccess(DomainDataRegionConfig regionConfig,
DomainDataRegionBuildingContext buildingContext) {
return new RedisDomainDataStorageAccessImpl(redisClient,
getOrCreateCache(regionConfig.getRegionName(), buildingContext.getSessionFactory()))
}
/**
* 创建查询结果缓存,该缓存用于hibernate的查询缓存
* @param regionName
* @param sessionFactory
* @return
*/
@Override
protected StorageAccess createQueryResultsRegionStorageAccess(String regionName, SessionFactoryImplementor sessionFactory) {
String defaultedRegionName = defaultRegionName(regionName, sessionFactory, DEFAULT_QUERY_RESULTS_REGION_UNQUALIFIED_NAME,
LEGACY_QUERY_RESULTS_REGION_UNQUALIFIED_NAMES)
return new RedisDomainDataStorageAccessImpl(redisClient, getOrCreateCache(defaultedRegionName, sessionFactory))
}
/**
* 创建时间戳缓存
* @param regionName
* @param sessionFactory
* @return
*/
@Override
protected StorageAccess createTimestampsRegionStorageAccess(String regionName, SessionFactoryImplementor sessionFactory) {
String defaultedRegionName = defaultRegionName(regionName, sessionFactory,
DEFAULT_UPDATE_TIMESTAMPS_REGION_UNQUALIFIED_NAME, LEGACY_UPDATE_TIMESTAMPS_REGION_UNQUALIFIED_NAMES)
return new RedisDomainDataStorageAccessImpl(redisClient, getOrCreateCache(defaultedRegionName, sessionFactory))
}
protected final String defaultRegionName(String regionName, SessionFactoryImplementor sessionFactory,
String defaultRegionName, List<String> legacyDefaultRegionNames) {
if (defaultRegionName.equals(regionName) && !cacheExists(regionName, sessionFactory)) {
for (String legacyDefaultRegionName : legacyDefaultRegionNames) {
if (cacheExists(legacyDefaultRegionName, sessionFactory)) {
SecondLevelCacheLogger.INSTANCE.usingLegacyCacheName(defaultRegionName, legacyDefaultRegionName)
return legacyDefaultRegionName
}
}
}
return regionName
}
protected boolean cacheExists(String unqualifiedRegionName, SessionFactoryImplementor sessionFactory) {
final String qualifiedRegionName = RegionNameQualifier.INSTANCE.qualify(unqualifiedRegionName,
sessionFactory.getSessionFactoryOptions())
return null != redisClient.createOrGetCache(qualifiedRegionName)
}
protected RedisCacheEntity<Object, Object> getOrCreateCache(String unqualifiedRegionName,
SessionFactoryImplementor sessionFactory) {
verifyStarted()
assert !RegionNameQualifier.INSTANCE.isQualified(unqualifiedRegionName, sessionFactory.getSessionFactoryOptions())
final String qualifiedRegionName = RegionNameQualifier.INSTANCE.qualify(unqualifiedRegionName,
sessionFactory.getSessionFactoryOptions())
return redisClient.createOrGetCache(qualifiedRegionName)
}
/**
* 简单的理解为初始化之前需要做的一些准备工作
* @param settings
* @param configValues
*/
@Override
protected void prepareForUse(SessionFactoryOptions settings, Map configValues) {
try {
this.redisClient = resolveRedisClient(configValues);
if (this.redisClient == null) {
throw new CacheException("Could not start Redis Client");
}
log.info("RedisRegionFactory is started.");
} catch (Exception e) {
throw new CacheException(e);
}
}
protected RedisClient resolveRedisClient(@SuppressWarnings("rawtypes") Map configValues) throws IOException {
redisService.withRedis { Jedis jedis ->
jedis.set("test", "RedisRegionFactory")
}
return new RedisClient(redisService)
}
/**
* 释放缓存
*/
@Override
protected void releaseFromUse() {
}
}
2、实现 DomainDataStorageAccess 接口
package middolhibernaterediscache
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.hibernate.cache.spi.support.DomainDataStorageAccess
import org.hibernate.engine.spi.SharedSessionContractImplementor
/**
* @Description: 实现redis 访问
* @Author: zhangjiayu@middol.com
* @CreateDate: 2020/7/31 11:07
* @Version: 1.0
*/
@Slf4j
@CompileStatic
class RedisDomainDataStorageAccessImpl implements DomainDataStorageAccess{
protected final RedisClient redisClient
protected final RedisCacheEntity<Object, Object> cache
RedisDomainDataStorageAccessImpl(RedisClient redisClient, RedisCacheEntity<Object, Object> cache) {
this.redisClient = redisClient
this.cache = cache
}
@Override
boolean contains(Object key) {
return cache.contains(key.toString())
}
@Override
Object getFromCache(Object key, SharedSessionContractImplementor session) {
try {
return cache.get(key)
}catch(e){
log.error(e.getMessage(),e)
return null
}
}
@Override
void putIntoCache(Object key, Object value, SharedSessionContractImplementor session) {
cache.put(key, value)
}
@Override
void evictData(Object key) {
cache.remove(key)
}
@Override
void evictData() {
cache.clear()
}
@Override
void release() {
redisClient.removeRegion(cache.getRegion())
}
}
3、实现单例 SingletonRedisRegionFactory
package middolhibernaterediscache
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import redis.clients.jedis.Jedis
import java.util.concurrent.atomic.AtomicInteger
@Slf4j
@CompileStatic
class SingletonRedisRegionFactory extends RedisRegionFactory {
/**
*
*/
private static final long serialVersionUID = 1L
private final AtomicInteger referenceCount = new AtomicInteger()
protected RedisClient resolveRedisClient(@SuppressWarnings("rawtypes") Map configValues) throws IOException {
try {
referenceCount.incrementAndGet()
redisService.withRedis { Jedis jedis ->
jedis.set("test", "SingletonRedisRegionFactory")
}
return new RedisClient(redisService)
} catch (RuntimeException e) {
referenceCount.decrementAndGet()
throw e
}
}
}
4、实现 StrategyRegistrationProvider 接口
package middolhibernaterediscache
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import org.hibernate.boot.registry.selector.SimpleStrategyRegistrationImpl
import org.hibernate.boot.registry.selector.StrategyRegistration
import org.hibernate.boot.registry.selector.StrategyRegistrationProvider
import org.hibernate.cache.spi.RegionFactory
@Slf4j
@CompileStatic
class RedisStrategyRegistrationProviderImpl implements StrategyRegistrationProvider {
@Override
@SuppressWarnings(["rawtypes"])
Iterable<StrategyRegistration> getStrategyRegistrations() {
final List<StrategyRegistration> strategyRegistrations = new ArrayList<>()
strategyRegistrations.add(new SimpleStrategyRegistrationImpl<RegionFactory>(RegionFactory.class,
RedisRegionFactory.class, "jedis", RedisRegionFactory.class.getName(),
RedisRegionFactory.class.getSimpleName(), "middol.redis.hibernate.RedisRegionFactory"))
strategyRegistrations.add(new SimpleStrategyRegistrationImpl<RegionFactory>(RegionFactory.class,
SingletonRedisRegionFactory.class, "jedis-singleton", SingletonRedisRegionFactory.class.getName(),
SingletonRedisRegionFactory.class.getSimpleName(),
"middol.redis.hibernate.RedisRegionFactor"))
return strategyRegistrations
}
}
5、RedisClient
package middolhibernaterediscache
import grails.plugins.redis.RedisService
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import redis.clients.jedis.Jedis
@Slf4j
@CompileStatic
class RedisClient {
RedisService redisService
private Map<String, RedisCacheEntity<Object, Object>> regionMap = new HashMap<>();
RedisClient(RedisService redisService) {
this.redisService = redisService
}
/**
* @return
*/
long dbSize() {
long size
redisService.withRedis { Jedis jedis ->
size = jedis.dbSize()
}
return size
}
/**
* @param region
* @param key
* @return
*/
boolean exists(String region, Object key) {
return createOrGetCache(region).contains(key.toString())
}
/**
* @param region
* @param key
* @return
*/
@SuppressWarnings("unchecked")
<T> T get(String region, Object key) {
T cacheItem = (T) createOrGetCache(region).get(key.toString())
log.trace("retrieve cache item. region=" + region + ", key=" + key + ", value=" + cacheItem)
return cacheItem
}
/**
* @param region
* @param key
* @param value
*/
void set(String region, Object key, Object value) {
set(region, key, value, null)
}
/**
* @param region
* @param key
* @param value
* @param expiry
*/
void set(String region, Object key, Object value, Integer expiry) {
log.trace("set cache item. region=" + region + ", key=" + key + ", timeout="
+ (expiry ?: 0))
createOrGetCache(region).put(key.toString(), value, expiry)
}
/**
* @param region
* @param key
* @return
*/
Object del(String region, Object key) {
return createOrGetCache(region).remove(key.toString())
}
/**
* @param region
*/
void clearRegion(String region) {
createOrGetCache(region).clear()
}
/**
* @param region
*/
void removeRegion(String region) {
regionMap.remove(region)
}
/**
*
*/
void flushDb() {
log.info("flush db...");
redisService.flushDB()
}
/**
* @param region
* @return
*/
RedisCacheEntity<Object, Object> createOrGetCache(String region) {
RedisCacheEntity<Object, Object> cache = regionMap.get(region)
if (null == cache) {
synchronized (regionMap) {
if (null == cache) {
cache = new RedisCacheEntity<>()
cache.init(region, redisService)
regionMap.put(region, cache)
}
}
}
return cache;
}
}
6、RedisCacheEntity
package middolhibernaterediscache
import grails.plugins.redis.RedisService
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
import middolhibernaterediscache.serializer.BinarySerializer
import middolhibernaterediscache.serializer.StringSerializer
import org.springframework.beans.factory.annotation.Autowired
import org.springframework.core.convert.converter.Converter
import org.springframework.core.serializer.support.SerializingConverter
import redis.clients.jedis.Jedis
/**
* @Description: redis 缓存实体
* @Author: zhangjiayu@middol.com
* @CreateDate: 2020/7/31 14:10
* @Version: 1.0
*/
@Slf4j
class RedisCacheEntity<K,V> implements CacheEntity<K,V>, Serializable {
private static final long serialVersionUID = 1L;
private String region;
/** Expiration in seconds */
Integer expiration = 3600
private final static StringSerializer stringSerializer = new StringSerializer()
private final BinarySerializer<V> valueSerializer = new BinarySerializer<>()
RedisService redisService
private static final String DOT = "."
@Override
void put(K key, V value, Integer expiryInSeconds) {
redisService.withRedis { Jedis jedis ->
byte[] keyByte = buildKey(key)
jedis.set(keyByte, serialize(value))
jedis.expire(keyByte, expiryInSeconds ?: expiration)
}
}
@Override
List<V> put(K key, V value) {
redisService.withRedis { Jedis jedis ->
byte[] keyByte = buildKey(key)
jedis.set(keyByte, serialize(value))
}
return null
}
@Override
V remove(K key) {
V value
redisService.withRedis { Jedis jedis ->
byte[] keyByte = buildKey(key)
if (0 < jedis.del(keyByte)) {
value = deserialize(jedis.get(keyByte))
}
}
return value
}
@Override
boolean contains(K key) {
boolean exits
redisService.withRedis { Jedis jedis ->
byte[] keyByte = buildKey(key)
exits = jedis.exists(keyByte)
}
return exits
}
@Override
V get(K key) {
V value
redisService.withRedis { Jedis jedis ->
byte[] keyByte = buildKey(key)
value = deserialize(jedis.get(keyByte))
}
return value
}
@Override
List<V> clear() {
List<V> list = new ArrayList<>()
redisService.withRedis { Jedis jedis ->
Set<String> keyList = jedis.keys(region + DOT + "*")
for (String key : keyList) {
if (0 < jedis.del(key)) {
byte[] keyByte = buildKey((K) key)
V value = deserialize(jedis.get(keyByte))
list.add(value)
}
}
}
return list
}
private byte[] buildKey(K key){
stringSerializer.serialize(region + DOT + key)
}
private Object deserialize(byte[] bytes) {
valueSerializer.deserialize(bytes)
}
private byte[] serialize(Object object) {
valueSerializer.serialize(object)
}
void init(String region, RedisService redisService) {
this.region = region
this.redisService = redisService
}
String getRegion() {
return region
}
}
7、CacheEntity
package middolhibernaterediscache
/**
* @Description: 缓存实体接口
* @Author: zhangjiayu@middol.com
* @CreateDate: 2020/7/31 13:47
* @Version: 1.0
*/
interface CacheEntity<K,V> {
/**
* @param key
* @param value
* @param expiryInSeconds
*/
void put(K key, V value, Integer expiryInSeconds);
/**
* @param key
* @param value
* @return values list
*/
List<V> put(K key, V value);
/**
* @param key
* @return value
*/
V remove(K key);
/**
* @param key
* @return whether it is included
*/
boolean contains(K key);
/**
* @param key
* @return value
*/
V get(K key);
/**
* @return values list
*/
List<V> clear();
}
8、Serializer
package middolhibernaterediscache.serializer
/**
*
* Serializer
* @param <T>
*
*/
interface Serializer<T> {
/**
*
*/
byte[] EMPTY_BYTES = new byte[0]
/**
* @param graph
* @return
*/
byte[] serialize(final T graph)
/**
* @param bytes
* @return
*/
T deserialize(final byte[] bytes)
}
9、BinarySerializer
package middolhibernaterediscache.serializer
import groovy.transform.CompileStatic
import groovy.util.logging.Slf4j
/**
*
* BinarySerializer
*
* @param <T>
*
*/
@Slf4j
@CompileStatic
class BinarySerializer<T> implements Serializer<T> {
@Override
byte[] serialize(final T graph) {
if (null == graph) {
return EMPTY_BYTES
}
try {
ByteArrayOutputStream os = new ByteArrayOutputStream()
ObjectOutputStream oos = new ObjectOutputStream(os)
oos.writeObject(graph)
oos.flush()
return os.toByteArray()
} catch (Exception e) {
log.warn("Fail to serializer graph. graph=" + graph, e)
return EMPTY_BYTES
}
}
@Override
@SuppressWarnings("unchecked")
T deserialize(final byte[] bytes) {
if (null == bytes || 0 == bytes.length) {
return null
}
try {
ByteArrayInputStream is = new ByteArrayInputStream(bytes)
ObjectInputStream ois = new ObjectInputStream(is)
return (T) ois.readObject()
} catch (Exception e) {
log.warn("Fail to deserialize bytes.", e)
return null
}
}
}
10、StringSerializer
package middolhibernaterediscache.serializer
import java.nio.charset.Charset;
/**
*
* StringSerializer
*
*/
class StringSerializer implements Serializer<String> {
/**
* 默认字符编码名称
*
* Default CharSet Name
*/
public static final String DEFAULT_CHARSET_NAME = "UTF-8";
/**
* 默认字符编码
*
* Default CharSet
*/
public static final Charset DEFAULT_CHARSET = Charset.forName(DEFAULT_CHARSET_NAME);
@Override
byte[] serialize(String str) {
return null == str ? EMPTY_BYTES : str.getBytes(DEFAULT_CHARSET);
}
@Override
String deserialize(byte[] bytes) {
return null == bytes ? null : new String(bytes, DEFAULT_CHARSET);
}
}
开启二级缓存
hibernate:
cache:
queries: true
use_second_level_cache: true
use_query_cache: true
region:
factory_class: middolhibernaterediscache.RedisRegionFactory
注意:
使用了RedisService,如果直接注解(@Autowired)进来会报错,报错如下:
"D:\Program Files\Java\jdk1.8.0_231\bin\java.exe" -XX:+TieredCompilation -XX:TieredStopAtLevel=1 -XX:CICompilerCount=3 -Djline.WindowsTerminal.directConsole=false -Dfile.encoding=UTF-8 -classpath C:\Users\zhang\AppData\Local\Temp\classpath269819685.jar org.grails.cli.GrailsCli run-app --plain-output
|Resolving Dependencies. Please wait...
CONFIGURE SUCCESSFUL in 3s
|Running application...
The Class-Path manifest attribute in C:\Users\zhang\.gradle\caches\modules-2\files-2.1\org.glassfish.jaxb\jaxb-runtime\2.3.1\dd6dda9da676a54c5b36ca2806ff95ee017d8738\jaxb-runtime-2.3.1.jar referenced one or more files that do not exist: file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/jaxb-api-2.3.1.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/txw2-2.3.1.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/istack-commons-runtime-3.0.7.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/stax-ex-1.8.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/FastInfoset-1.2.15.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/org.glassfish.jaxb/jaxb-runtime/2.3.1/dd6dda9da676a54c5b36ca2806ff95ee017d8738/javax.activation-api-1.2.0.jar
The Class-Path manifest attribute in C:\Users\zhang\.gradle\caches\modules-2\files-2.1\com.sun.xml.bind\jaxb-impl\2.3.1\a1a12b85ba1435b4189e065f7dafcc3fb9410d38\jaxb-impl-2.3.1.jar referenced one or more files that do not exist: file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/jaxb-runtime-2.3.1.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/txw2-2.3.1.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/istack-commons-runtime-3.0.7.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/stax-ex-1.8.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/FastInfoset-1.2.15.jar,file:/C:/Users/zhang/.gradle/caches/modules-2/files-2.1/com.sun.xml.bind/jaxb-impl/2.3.1/a1a12b85ba1435b4189e065f7dafcc3fb9410d38/javax.activation-api-1.2.0.jar
2020-08-03 11:17:14.054 ERROR --- [ restartedMain] o.s.boot.SpringApplication : Application run failed
org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'openSessionInViewInterceptor': Cannot resolve reference to bean 'hibernateDatastore' while setting bean property 'hibernateDatastore'; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:314)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveValueIfNecessary(BeanDefinitionValueResolver.java:110)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.applyPropertyValues(AbstractAutowireCapableBeanFactory.java:1674)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:1426)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:592)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:860)
at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:878)
at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:550)
at org.springframework.boot.web.servlet.context.ServletWebServerApplicationContext.refresh(ServletWebServerApplicationContext.java:141)
at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:744)
at org.springframework.boot.SpringApplication.refreshContext(SpringApplication.java:391)
at org.springframework.boot.SpringApplication.run(SpringApplication.java:312)
at grails.boot.GrailsApp.run(GrailsApp.groovy:99)
at grails.boot.GrailsApp.run(GrailsApp.groovy:485)
at grails.boot.GrailsApp.run(GrailsApp.groovy:472)
at grails4hibernaterediscache.Application.main(Application.groovy:11)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49)
Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'hibernateDatastore': Bean instantiation via constructor failed; nested exception is org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:304)
at org.springframework.beans.factory.support.ConstructorResolver.autowireConstructor(ConstructorResolver.java:285)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.autowireConstructor(AbstractAutowireCapableBeanFactory.java:1340)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:1186)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:555)
at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:515)
at org.springframework.beans.factory.support.AbstractBeanFactory.lambda$doGetBean$0(AbstractBeanFactory.java:320)
at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:226)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:318)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:199)
at org.springframework.beans.factory.support.BeanDefinitionValueResolver.resolveReference(BeanDefinitionValueResolver.java:303)
... 25 common frames omitted
Caused by: org.springframework.beans.BeanInstantiationException: Failed to instantiate [org.grails.orm.hibernate.HibernateDatastore]: Constructor threw exception; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:184)
at org.springframework.beans.factory.support.SimpleInstantiationStrategy.instantiate(SimpleInstantiationStrategy.java:117)
at org.springframework.beans.factory.support.ConstructorResolver.instantiate(ConstructorResolver.java:300)
... 35 common frames omitted
Caused by: org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.cache.spi.CacheImplementor]
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:275)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.initializeService(AbstractServiceRegistryImpl.java:237)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.getService(AbstractServiceRegistryImpl.java:214)
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.getService(SessionFactoryServiceRegistryImpl.java:98)
at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:245)
at org.hibernate.boot.internal.SessionFactoryBuilderImpl.build(SessionFactoryBuilderImpl.java:469)
at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:708)
at org.grails.orm.hibernate.cfg.HibernateMappingContextConfiguration.buildSessionFactory(HibernateMappingContextConfiguration.java:287)
at org.grails.orm.hibernate.connections.HibernateConnectionSourceFactory.create(HibernateConnectionSourceFactory.java:86)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:39)
at org.grails.orm.hibernate.connections.AbstractHibernateConnectionSourceFactory.create(AbstractHibernateConnectionSourceFactory.java:23)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.create(AbstractConnectionSourceFactory.java:64)
at org.grails.datastore.mapping.core.connections.AbstractConnectionSourceFactory.create(AbstractConnectionSourceFactory.java:52)
at org.grails.datastore.mapping.core.connections.ConnectionSourcesInitializer.create(ConnectionSourcesInitializer.groovy:24)
at org.grails.orm.hibernate.HibernateDatastore.<init>(HibernateDatastore.java:212)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.springframework.beans.BeanUtils.instantiateClass(BeanUtils.java:172)
... 37 common frames omitted
Caused by: java.lang.IllegalStateException: Cache provider not started
at org.hibernate.cache.spi.AbstractRegionFactory.verifyStarted(AbstractRegionFactory.java:65)
at org.hibernate.cache.spi.support.RegionFactoryTemplate.buildTimestampsRegion(RegionFactoryTemplate.java:66)
at org.hibernate.cache.internal.EnabledCaching.<init>(EnabledCaching.java:85)
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:33)
at org.hibernate.engine.spi.CacheInitiator.initiateService(CacheInitiator.java:24)
at org.hibernate.service.spi.SessionFactoryServiceInitiator.initiateService(SessionFactoryServiceInitiator.java:30)
at org.hibernate.service.internal.SessionFactoryServiceRegistryImpl.initiateService(SessionFactoryServiceRegistryImpl.java:62)
at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
... 56 common frames omitted
Caused by: org.hibernate.cache.CacheException: java.lang.NullPointerException
at middolhibernaterediscache.RedisRegionFactory.prepareForUse(RedisRegionFactory.groovy:139)
at org.hibernate.cache.spi.AbstractRegionFactory.start(AbstractRegionFactory.java:91)
at org.hibernate.cache.internal.EnabledCaching.<init>(EnabledCaching.java:82)
... 61 common frames omitted
Caused by: java.lang.NullPointerException: null
at middolhibernaterediscache.RedisRegionFactory.resolveRedisClient(RedisRegionFactory.groovy:144)
at middolhibernaterediscache.RedisRegionFactory.prepareForUse(RedisRegionFactory.groovy:133)
... 63 common frames omitted
解决办法:
RedisService redisService = Holders.grailsApplication.mainContext.getBean(RedisService.class)