Spring MVC 和 EhCache 不工作

Spring MVC and EhCache is not working

我正在尝试将 ehcache 集成到 spring mvc 和 hibernate 应用程序中,但是下面的代码无法正常工作。我遵循了 link - how to use ehcache in spring mvc with hibernate 但我仍然面临问题。当我启动服务器时,这个问题就来了。我正在使用 spring 5.0.5

springmvc.xml

<beans:bean id="sessionFactory" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
        <beans:property name="dataSource" ref="dataSource" />
        <beans:property name="packagesToScan">
            <beans:array>
                <beans:value>com.kalavakuri.springmvcandorm</beans:value>
            </beans:array>
        </beans:property>
        <beans:property name="hibernateProperties">
            <beans:props>
                <beans:prop key="hibernate.dialect">${hibernate.dialect}</beans:prop>
                <beans:prop key="hibernate.show_sql">${hibernate.show_sql}</beans:prop>
                <beans:prop key="hibernate.cache.use_second_level_cache">true</beans:prop>
                <beans:prop key="hibernate.cache.region.factory_class">org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory</beans:prop>
                <beans:prop key="hibernate.cache.provider_configuration_file_resource_path">ehcache.xml</beans:prop>
                <beans:prop key="hibernate.cache.use_query_cache">true</beans:prop>
                <!-- <beans:prop key="hibernate.hbm2ddl.auto">${hibernate.hbm2ddl.auto}</beans:prop> -->
            </beans:props>
        </beans:property>
    </beans:bean>

ehcache.xml

<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:noNamespaceSchemaLocation="http://ehcache.org/ehcache.xsd">

    <diskStore path="java.io.tmpdir" />
    <!--defaultCache eternal="false" maxElementsInMemory="1000" maxElementsOnDisk="10000" 
        overflowToDisk="true" diskPersistent="true" timeToLiveSeconds="300" statistics="true" 
        copyOnWrite="true" / -->

    <cache name="student" maxElementsInMemory="100000"
        eternal="true" overflowToDisk="false" memoryStoreEvictionPolicy="LFU"
        statistics="true" timeToLiveSeconds="3600" />

</ehcache>

I am getting below error:

Caused by: org.hibernate.cache.CacheException: On-the-fly creation of JCache Cache objects is not supported [org.hibernate.cache.spi.TimestampsRegion]
    at org.hibernate.cache.ehcache.internal.EhcacheRegionFactory.createCache(EhcacheRegionFactory.java:106)
    at org.hibernate.cache.ehcache.internal.EhcacheRegionFactory.getOrCreateCache(EhcacheRegionFactory.java:100)
    at org.hibernate.cache.ehcache.internal.EhcacheRegionFactory.createTimestampsRegionStorageAccess(EhcacheRegionFactory.java:86)
    at org.hibernate.cache.spi.support.RegionFactoryTemplate.buildTimestampsRegion(RegionFactoryTemplate.java:70)
    at org.hibernate.cache.internal.EnabledCaching.<init>(EnabledCaching.java:80)
    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:68)
    at org.hibernate.service.internal.AbstractServiceRegistryImpl.createService(AbstractServiceRegistryImpl.java:263)
    ... 99 more

根据 hibernate documentation 你必须创建其他 2 个缓存区域

  1. org.hibernate.cache.spi.UpdateTimestampsCache: thios 应该尽可能大(最好永不过期)
  2. org.hibernate.cache.internal.StandardQueryCache

Hibernate 无法即时将它们打包(尤其是第一个)

实际上,通过使用 ehcahe 3 和 hibernate 5,我使用了这个配置:

@Configuration
@EnableCaching
public class CacheConfiguration extends CachingConfigurerSupport
{
    @Autowired
    private Environment env;
    @Bean("cacheManager")
    @Override
    public org.springframework.cache.CacheManager cacheManager()
    {

        return new JCacheCacheManager(createCacheManager());
    }
    private CacheManager createCacheManager()
    {
        long dimensioneCache = new Long(env.getProperty("arca.context.cache.size"));
        long ttlMillisecondi = new Long(env.getProperty("arca.context.cache.ttl"));
        org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration = CacheConfigurationBuilder.
                                                                                                newCacheConfigurationBuilder(Object.class, Object.class, 
                                                                                                ResourcePoolsBuilder.heap(dimensioneCache)
                                                                                                ).withExpiry(Expirations.timeToLiveExpiration(new org.ehcache.expiry.Duration(ttlMillisecondi, TimeUnit.MILLISECONDS))).build();
        Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = createCacheConfigurations(cacheConfiguration);
        //Creo la cache di hibernate org.hibernate.cache.spi.UpdateTimestampsCache. 
        //Dalla documentazione di hibernate https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#caching
        ResourcePoolsBuilder rpb = ResourcePoolsBuilder.heap(dimensioneCache*1000000);
        org.ehcache.config.CacheConfiguration<Object, Object> eternalCacheConfiguration = CacheConfigurationBuilder.newCacheConfigurationBuilder(Object.class, Object.class, rpb).withExpiry(Expirations.noExpiration()).build();
        caches.put("org.hibernate.cache.spi.UpdateTimestampsCache", eternalCacheConfiguration);
        EhcacheCachingProvider provider = getCachingProvider();
        DefaultConfiguration configuration = new DefaultConfiguration(caches, provider.getDefaultClassLoader());
        CacheManager result = provider.getCacheManager(provider.getDefaultURI(), configuration);
        return result;
    }

    private Map<String, org.ehcache.config.CacheConfiguration<?, ?>> createCacheConfigurations(org.ehcache.config.CacheConfiguration<Object, Object> cacheConfiguration)
    {
        Map<String, org.ehcache.config.CacheConfiguration<?, ?>> caches = new HashMap<>();
        // I'm searcing for all objects with @Entity annotation in order to create cache regions
        ClassPathScanningCandidateComponentProvider scanner = new ClassPathScanningCandidateComponentProvider(false);
        scanner.addIncludeFilter(new AnnotationTypeFilter(Entity.class));
        for (BeanDefinition bd : scanner.findCandidateComponents("it.test.models"))
        {
            String className = bd.getBeanClassName();
            caches.put(className, cacheConfiguration);
        }
        //org.hibernate.cache.internal.StandardQueryCache creation
        caches.put("org.hibernate.cache.internal.StandardQueryCache", cacheConfiguration);
        return caches;
    }

    private EhcacheCachingProvider getCachingProvider()
    {
        return (EhcacheCachingProvider) Caching.getCachingProvider();
    }
}

在我的休眠配置中,我使用了这个缓存工厂it.olegna.tests.hibernate.cache.config.JCacheRegionFactory它的代码如下:

public class JCacheRegionFactory extends org.hibernate.cache.jcache.JCacheRegionFactory
{
    private static final long serialVersionUID = 1021281213463444167L;

    @Override
    protected Cache<Object, Object> createCache(String regionName, Properties properties, CacheDataDescription metadata)
    {
        throw new IllegalArgumentException("Unknown hibernate cache: " + regionName);
    }
}

我遇到了同样的问题。通过将@EnableCaching 添加到spring 引导应用程序@SpringBootApplication 问题得到解决。请试试。