EHCache配置+Spring Boot:NoCacheRegionFactoryAvailableException

7

我正在尝试配置基于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二级缓存是不同的东西... - M. Deinum
EHCache被用作Hibernate的二级缓存,在我的情况下,我正在使用Spring Data JPA(与Hibernate一起)。那么我的困惑在哪里呢? - Tal Etinger
如所述,Spring的缓存抽象和在JPA提供程序中使用二级缓存是没有任何关系的。基本上,你为Spring Caching设置并没有做任何事情,或者至少与你遇到的错误没有关系。 - M. Deinum
在这里(http://www.ehcache.org/documentation/2.8/integrations/hibernate),您可以找到有关`EhCache`和Hibernate 3.3 / 4.x的一些有用细节。它还显示了hibernate.cache.region.factory_class的值。 - ROMANIA_engineer
在我的情况下,我忘记在grails-app/conf/(Grails 3)中创建我的application.yml文件。 - Eduardo Cuomo
1个回答

19

错误信息的关键部分是:

应用程序中使用了二级缓存,但未给出属性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


我遇到了同样的问题,但是使用=代替:,结果不起作用。为什么属性格式不同呢?抱歉这不是这里应该问的问题,但是感谢你让我找到了我的问题所在(并被这个问题困扰)。 - HankCa
2
您可以在属性文件中使用=:来分隔键和值。 - Andy Wilkinson
是的,这就是我想的。我再试了一遍,现在可以了。之前可能复制进来了一个奇怪的字符。现在一切都好了! - HankCa

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接