Spring+Hibernate集群缓存PoC问题:数据库对象未存入BigMemory Max
解决Ehcache + Terracotta + JPA事务缓存不生效的问题
我看了你遇到的问题——用JPA结合Ehcache+Terracotta(BigMemory Max)做事务缓存PoC,手动调用bigMemory.put()能成功把对象存入缓存,但通过JPA操作后Terracotta控制台始终显示缓存对象数为0。这大概率是JPA与Ehcache的集成配置没到位,或者事务缓存的触发逻辑没走对。下面给你几个具体的排查和解决方向:
1. 先把JPA二级缓存的核心配置补上
Hibernate默认是关闭二级缓存的,你现在的配置里完全没开启这个功能,自然不会自动把实体存入Ehcache:
- 在
application.properties中添加Hibernate缓存开启配置:# 开启二级缓存 spring.jpa.properties.hibernate.cache.use_second_level_cache=true # 指定用Ehcache作为缓存区域工厂 spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.ehcache.EhCacheRegionFactory # 可选:如果需要缓存findAll这类查询结果,开启查询缓存 spring.jpa.properties.hibernate.cache.use_query_cache=true - 给你的
Note实体类加上缓存注解,告诉Hibernate要把这个实体的实例存入缓存:
这里的@Entity @Table(name = "notes") @Cacheable @Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL, region = "com.example.pocehcache.model.Note") public class Note implements Serializable { // ... 你的现有代码 }region值必须和你ehcache.xml里定义的缓存name完全一致,这样Hibernate才会把实体放到你配置的分布式缓存中。
2. 确保Atomikos与Ehcache的XA事务集成正确
你开启了Ehcache的transactionalMode="xa",要保证Spring的事务管理和Atomikos的XA事务能正确联动:
- 检查是否引入了对应版本的
ehcache-transactions依赖,这是Ehcache支持XA事务的必要jar包。 - 显式配置Atomikos的事务管理器(Spring默认的事务管理器不支持XA),替换掉默认的事务管理逻辑:
这样Spring的@Configuration public class AtomikosConfig { @Bean public PlatformTransactionManager transactionManager() throws SystemException { JtaTransactionManager transactionManager = new JtaTransactionManager(); transactionManager.setTransactionManager(atomikosTransactionManager()); transactionManager.setUserTransaction(atomikosUserTransaction()); return transactionManager; } @Bean public UserTransaction atomikosUserTransaction() throws SystemException { UserTransactionImp userTransactionImp = new UserTransactionImp(); userTransactionImp.setTransactionTimeout(300); return userTransactionImp; } @Bean(initMethod = "init", destroyMethod = "close") public TransactionManager atomikosTransactionManager() { UserTransactionManager userTransactionManager = new UserTransactionManager(); userTransactionManager.setForceShutdown(false); return userTransactionManager; } }@Transactional注解才会使用Atomikos的XA事务管理器,保证缓存操作和数据库操作的事务一致性。
3. 验证缓存触发时机与查询缓存配置
- JPA的二级缓存是在事务提交后才会写入的,所以调用完
createNote或者getAllNotes后,不要立刻去看Terracotta控制台,等几秒让事务提交完成再检查。 - 如果要缓存
findAll这类批量查询的结果,需要给Repository的方法加上查询缓存注解:
否则Hibernate只会缓存单个实体对象,不会缓存查询结果集。@Repository public interface NoteRepository extends JpaRepository<Note, Long> { @Override @QueryHints(@QueryHint(name = org.hibernate.annotations.QueryHints.CACHEABLE, value = "true")) List<Note> findAll(); }
4. 排查日志定位问题
开启Hibernate、Ehcache和Atomikos的Debug日志,能帮你快速定位缓存是否被正确触发:
在application.properties中添加:
logging.level.org.hibernate.cache=DEBUG logging.level.net.sf.ehcache=DEBUG logging.level.com.atomikos=DEBUG
查看日志里是否有类似CachePut(Hibernate)或Element added to cache(Ehcache)的日志:
- 如果没有这类日志:说明缓存逻辑根本没触发,回到第一步检查JPA缓存配置。
- 如果有日志但Terracotta控制台没显示:检查Terracotta服务器连接是否正常(日志里会有连接成功的提示),或者缓存region名称是否匹配。
内容的提问来源于stack exchange,提问作者snesh
相关产品推荐
相关产品推荐

