Grails4 自定义二级缓存(使用Jedis插件),重写RegionFactoryTemplate

102 篇文章 2 订阅

参考hibernate二级缓存实现

适合使用集群服务

效果:

创建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)

 

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值