You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

升级Hibernate 5后EhCache配置失效:JCache相关技术咨询

我来逐个拆解你的三个问题,结合Hibernate 5和Ehcache 3的实际情况给你说明:

问题1:能否在Hibernate 5 + Ehcache 3环境下继续使用SingletonEhCacheRegionFactory?

答案是不行,核心原因有两点:

  • SingletonEhCacheRegionFactory是Hibernate专门为Ehcache 2.x开发的集成类,它依赖的是Ehcache 2的内部API以及旧版Hibernate缓存SPI(比如你报错里的org.hibernate.cache.TimestampsRegion,这个类在Hibernate 5的缓存SPI重构后已经被移除/重命名)。
  • 你当前引入的是Ehcache 3.x,它的API和架构完全重构,不再兼容Ehcache 2的生态,哪怕这个类没被标记为过时,也无法和Ehcache 3配合工作。

如果非要沿用类似旧版的Ehcache集成逻辑,你得换回Ehcache 2.x版本,同时确保hibernate-ehcache依赖版本和Hibernate核心版本匹配,但显然这不推荐——Ehcache 2早已停止维护,存在安全风险。

问题2:新的JCache是什么?它仅用于方法返回值缓存吗?

JCache(JSR-107)是Java官方制定的标准化缓存API规范,它定义了一套通用的缓存操作接口,让不同缓存实现(比如Ehcache 3、Caffeine、Redis等)可以统一接入,不用关心具体实现细节。

它绝对不是只用于方法缓存:

  • Hibernate的二级缓存(实体缓存):可以通过JCache作为缓存提供者,把实体数据缓存到Ehcache 3中,和你之前用Ehcache 2的二级缓存功能完全一致。
  • Hibernate的查询缓存:同样可以通过JCache实现,Hibernate会把查询结果集缓存到JCache指定的区域里。
  • 方法缓存(比如Spring的@Cacheable)只是JCache的一个应用场景,它的核心价值是提供通用缓存能力,支持各种缓存需求。
问题3:如何将旧的EhCache配置转换为新版本?

Ehcache 3的配置格式和Ehcache 2差异极大,你遇到的SAX解析错误就是因为旧配置的根元素<ehcache>不符合Ehcache 3的XML schema。下面是把你的旧配置转换成Ehcache 3格式的完整示例:

第一步:编写新的Ehcache 3配置文件(比如命名为ehcache3.xml

<?xml version="1.0" encoding="UTF-8"?>
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="https://www.ehcache.org/v3 https://www.ehcache.org/schema/ehcache-core-3.0.xsd"
        xmlns="https://www.ehcache.org/v3">

    <!-- 对应旧版diskStore,设置磁盘存储路径 -->
    <persistence directory="${java.io.tmpdir}/ehcache"/>

    <!-- 对应旧版defaultCache,作为所有缓存的默认模板 -->
    <defaults>
        <expiry>
            <tti>300</tti> <!-- 对应timeToIdleSeconds: 300秒 -->
            <ttl>600</ttl> <!-- 对应timeToLiveSeconds: 600秒 -->
        </expiry>
        <heap unit="entries">10000</heap> <!-- 对应maxElementsInMemory: 10000 -->
        <offheap unit="MB">30</offheap> <!-- 对应diskSpoolBufferSizeMB: 30MB,用堆外存储替代更合理 -->
        <disk persistent="true" unit="entries">10000</disk> <!-- 对应maxElementsOnDisk: 10000 -->
        <eviction-policy>LRU</eviction-policy> <!-- 对应memoryStoreEvictionPolicy: LRU -->
    </defaults>

    <!-- Hibernate更新时间戳缓存 -->
    <cache alias="org.hibernate.cache.spi.UpdateTimestampsCache">
        <heap unit="entries">10000</heap>
        <expiry>
            <none/> <!-- 对应旧版eternal="false"但未设置过期时间,这里表示永不过期 -->
        </expiry>
    </cache>

    <!-- Hibernate标准查询缓存 -->
    <cache alias="org.hibernate.cache.internal.StandardQueryCache">
        <heap unit="entries">10000</heap>
        <expiry>
            <ttl>300</ttl> <!-- 对应timeToLiveSeconds: 300秒 -->
        </expiry>
    </cache>

    <!-- 自定义实体缓存:br.com.atlantico.toi.model.calc.Anomalia -->
    <cache alias="br.com.atlantico.toi.model.calc.Anomalia">
        <heap unit="entries">10000</heap>
        <expiry>
            <tti>300</tti>
            <ttl>600</ttl>
        </expiry>
    </cache>
</config>

第二步:调整Hibernate的JCache配置

先移除hibernate-ehcache依赖(它是Ehcache 2的整合包,和Ehcache 3冲突),保留hibernate-jcacheehcache及其他Hibernate核心依赖。然后修改Hibernate的properties配置:

// 开启二级缓存和查询缓存
properties.put(Environment.USE_SECOND_LEVEL_CACHE, "true");
properties.put(Environment.USE_QUERY_CACHE, "true");

// 指定JCache缓存区域工厂
properties.put(Environment.CACHE_REGION_FACTORY, JCacheRegionFactory.class.getName());
// 指定Ehcache 3作为JCache提供者
properties.put("hibernate.javax.cache.provider", org.ehcache.jsr107.EhcacheCachingProvider.class.getName());
// 指向新的Ehcache 3配置文件
properties.put("hibernate.javax.cache.uri", "App/config/ehcache3.xml");

额外说明:

  • Ehcache 3支持堆内、堆外、磁盘多层缓存,你可以根据业务需求调整存储层级和参数。
  • 除了XML配置,也可以用Java代码方式配置Ehcache 3,再通过Hibernate的JCache集成接入。

内容的提问来源于stack exchange,提问作者mjs

火山引擎 最新活动