我正在尝试设置事务性ehcache,使用Spring @Cacheable和@Transactional .
我的缓存可以正常使用@Cacheable,但是只要我设置缓存以使用本地事务:
<cache name="currencyCodeMaps" maxElementsInMemory="100" overflowToDisk="false" timeToIdleSeconds="5" timeToLiveSeconds="600" memoryStoreEvictionPolicy="LRU" transactionalMode="local"/>
当我访问缓存时,我收到错误:
net.sf.ehcache.transaction.TransactionException: transaction not started
即使相同的方法注释@Transactional . 我的Spring事务管理器是:
org.springframework.orm.jpa.JpaTransactionManager
ehcache documentation表示本地交易是明确控制的:
本地事务不受事务管理器控制 . 相反,有一个显式API,使用cacheManager.getTransactionController()获取CacheManager的TransactionController的引用,并明确调用事务中的步骤
但这很难,因为我想将我的ehcache事务与数据库事务同步,而数据库事务由@Transactional控制 .
有没有办法让本地Ehcache事务与Spring @Transactional一起使用?
2 回答
是的,有一种方法可以实现你的目标 .
org.springframework.data.transaction.ChainedTransactionManager
源代码和测试用例可以找到here
该解决方案具有显着缺点,ehcache的事务协调器不支持挂起/恢复操作,因此内部事务(PROPAGATION_REQUIRES_NEW)是不可能的 . 这就是为什么我必须找到另一个 .
另一种选择是根本不使用本地ehcache事务,并使用
org.springframework.cache.transaction.AbstractTransactionSupportingCacheManager#setTransactionAware
来装饰缓存以推迟操作直到事务结束 . 但它有以下缺点:在事务提交之前,被驱逐的密钥在事务内保持可访问状态
putIfAbsent
操作未延期这对我来说是一个问题,所以我以不同的方式实现了这个功能 . 检查'me.qnox.springframework.cache.tx.TxAwareCacheManagerProxy',上面描述的问题已解决,在同一个存储库中
您不希望本地事务,您想要Ehcache支持的XA事务 .
查看Ehcache 2.10.x或Ehcache 2.8.x的文档 .