EHCache 配置 + Spring Boot:NoCacheRegionFactoryAvailableException

Posted

技术标签:

【中文标题】EHCache 配置 + Spring Boot:NoCacheRegionFactoryAvailableException【英文标题】:EHCache Configuration + Spring Boot: NoCacheRegionFactoryAvailableException 【发布时间】:2015-03-04 07:46:09 【问题描述】:

我正在尝试使用基于 EHCache 的二级缓存配置 Spring Boot 应用程序。 我遇到了这个异常:

Exception in thread "main" org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaAutoConfiguration.class]: Invocation of init method     failed; nested exception is org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the     hibernate.cache.region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1554)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:539)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193)
    at org.springframework.context.support.AbstractApplicationContext.getBean(AbstractApplicationContext.java:975)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:752)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482)
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109)
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952)
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941)
    at com.yes.wizard.Application.main(Application.java:30)
    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:483)
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:134)
Caused by: org.hibernate.cache.NoCacheRegionFactoryAvailableException: Second-level cache is used in the application, but property hibernate.cache.region.factory_class is not given; please either disable second level cache or set correct region factory using the hibernate.cache.    region.factory_class setting and make sure the second level cache provider (hibernate-infinispan, e.g.) is available on the classpath.
    at org.hibernate.cache.internal.NoCachingRegionFactory.buildEntityRegion(NoCachingRegionFactory.java:83)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:364)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1859)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:852)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl$4.perform(EntityManagerFactoryBuilderImpl.java:845)
    at org.hibernate.boot.registry.classloading.internal.ClassLoaderServiceImpl.withTccl(ClassLoaderServiceImpl.java:398)
    at org.hibernate.jpa.boot.internal.EntityManagerFactoryBuilderImpl.build(EntityManagerFactoryBuilderImpl.java:844)
    at org.hibernate.jpa.HibernatePersistenceProvider.createContainerEntityManagerFactory(HibernatePersistenceProvider.java:152)
    at org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean.createNativeEntityManagerFactory(LocalContainerEntityManagerFactoryBean.java:338)
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.afterPropertiesSet(AbstractEntityManagerFactoryBean.java:318)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1613)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1550)
    ... 20 more    

这是我的配置:

Application.class:

@EnableAutoConfiguration
@Configuration
@ComponentScan
@ImportResource(value = "/ws.xml")
public class Application 

    public static void main(String[] args) throws Exception 
        SpringApplication.run(Application.class, args);
    

CacheConfig.class:

@Configuration
@EnableCaching
public class CachingConfig implements CachingConfigurer 

    @Bean
    @Override
    public CacheManager cacheManager() 
        EhCacheCacheManager cacheManager = new EhCacheCacheManager();
        cacheManager.setCacheManager(ehCacheManagerFactoryBean().getObject());
        return cacheManager;
    

    @Bean
    @Override
    public KeyGenerator keyGenerator() 
        return new SimpleKeyGenerator();
    

    @Bean
    public EhCacheManagerFactoryBean ehCacheManagerFactoryBean() 
        EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();
        ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("ehcache.xml"));
        ehCacheManagerFactoryBean.setCacheManagerName("messageCache");
        ehCacheManagerFactoryBean.setShared(true);
        return ehCacheManagerFactoryBean;
    

我的实体:

@Entity
@XmlRootElement
@Table(name = "my_entity")
@Cacheable(value = true)
@Cache(usage = CacheConcurrencyStrategy.READ_ONLY)
public class MyEntity  ... 

ehcache.xml:

<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
    <defaultCache eternal="true" maxElementsInMemory="100" overflowToDisk="false" />
    <cache name="messageCache" maxElementsInMemory="10" eternal="true" overflowToDisk="false" />
</ehcache>

这是什么原因造成的?

【问题讨论】:

Spring 缓存和 Hibernate 二级缓存是不同的东西...... EHCache 用作休眠的二级缓存,在我的情况下,我使用的是 spring data jpa(带有休眠)。那么我的困惑在哪里? 如前所述,springs 缓存抽象和为您的 JPA 提供程序使用二级缓存彼此无关。基本上,您对 Spring Caching 的设置不会做任何事情,或者至少与您遇到的错误无关。 在这里 (ehcache.org/documentation/2.8/integrations/hibernate) 您可以找到有关 EhCache 和 Hibernate 3.3 / 4.x 的一些有用的详细信息。它还显示了hibernate.cache.region.factory_class 的值。 就我而言,我忘记将我的application.yml 文件创建到grails-app/conf/(Grails 3)中 【参考方案1】:

错误信息的关键部分是:

应用中使用了二级缓存,但没有给出属性hibernate.cache.region.factory_class;请禁用二级缓存或使用hibernate.cache.region.factory_class 设置设置正确的区域工厂,并确保二级缓存提供程序(例如hibernate-infinispan)在类路径中可用

您可以在 Spring Boot 的 application.properties 文件中设置 factory_class 属性。例如:

spring.jpa.properties.hibernate.cache.region.factory_class: org.hibernate.cache.ehcache.EhCacheRegionFactory

您需要使用的类名将取决于您的 EhCache 依赖项;在这种情况下,我使用了hibernate-ehcache

【讨论】:

我有相同的,但= 而不是:,这不起作用。为什么不同的属性格式?抱歉,这不是这里的问题,但多亏了你,我发现了我的问题(并且被这个问题打动了)。 您可以使用=: 来分隔属性文件中的键和值 是的,我就是这么想的。我再次尝试并工作。我之前复制的时候一定有一个有趣的角色。一切顺利!

以上是关于EHCache 配置 + Spring Boot:NoCacheRegionFactoryAvailableException的主要内容,如果未能解决你的问题,请参考以下文章

spring boot学习(十三)SpringBoot缓存(EhCache 2.x 篇)

使用 EhCache 进行 Spring Boot 缓存不起作用

Spring Boot 2.x基础教程:EhCache缓存的使用

Spring Boot整合EhCache

SpringBoot缓存(Ehcache)

Spring Boot Oauth2缓存UserDetails到Ehcache