gpt4 book ai didi

java - Spring事务感知缓存不起作用

转载 作者:行者123 更新时间:2023-12-01 23:19:25 26 4
gpt4 key购买 nike

我正在使用 Spring 缓存抽象,使用 Ehcache 作为缓存提供程序。我正在尝试将缓存操作附加到 Spring JPA 事务,但无法这样做。

即使事务失败/回滚缓存也会发生。

配置,

        @Bean
public EhCacheManagerFactoryBean cacheManagerUsingSpringApi() {
EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManagerFactoryBean();

// provide xml file for ehcache configuration/
ehCacheManagerFactoryBean.setConfigLocation(new ClassPathResource("spring-cache-abs-ehcache.xml"));

return ehCacheManagerFactoryBean;
}

@Bean
public org.springframework.cache.CacheManager ehCacheCacheManager() {
final EhCacheCacheManager ehCacheCacheManager = new EhCacheCacheManager(cacheManagerUsingSpringApi().getObject());
ehCacheCacheManager.setTransactionAware(true); // Setting transaction aware
return ehCacheCacheManager;
}

spring-cache-abs-ehcache.xml,

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

<cache name="EmployeeCache"
maxEntriesLocalHeap="10000"
eternal="false"
timeToIdleSeconds="300" timeToLiveSeconds="600"
memoryStoreEvictionPolicy="LFU"
transactionalMode="off">
<persistence strategy="localTempSwap" />
</cache>
</ehcache>

员工存储库,

    public interface EmployeeRepository extends JpaRepository<Employee, Long>, CustomEmployeeRepository {
}

交易方法,

    @Repository
public class EmployeeRepositoryImpl implements CustomEmployeeRepository {

@PersistenceContext
private EntityManager entityManager;

@Autowired
private CacheManager cacheManager;

// THIS METHOD SHOULD NOT PUT INTO CACHE WITH NEW NAME
@Override
@Transactional
@Cacheable(cacheNames = "EmployeeCache", key = "#a0.id")
public Employee customUpdate(Employee employee) {
employee.setFirstName(UUID.randomUUID().toString());
entityManager.merge(employee);

// rolling back transaction
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

return employee;
}
}

测试用例(调用者),

    @Test
public void testCustomUpdate() {
// GIVEN
Employee employee = new Employee();
employee.setFirstName(UUID.randomUUID().toString());
employee.setLastName(UUID.randomUUID().toString());
final Employee savedEmployee = employeeRepository.save(employee);

// WHEN
final Employee updatedEmployee = employeeRepository.customUpdate(savedEmployee);

// THEN
final Cache employeeCache = cacheManager.getCache("EmployeeCache");
final Cache.ValueWrapper object = employeeCache.get(updatedEmployee.getId());
assertNull(object);
}

测试应该成功,即如果事务在该方法中回滚,则 spring 不应将数据放入方法 employeeRepository.customUpdate 中的缓存中。但是,即使事务失败,Spring 也会将数据放入缓存中。注意:奇怪的是,如果缓存中已经存在条目,那么如果事务失败,@CachePut 不会更新缓存中的条目。

因此,如果我用 @CachePut(cacheNames = "EmployeeCache", key = "#result.id") 注释 employeeRepository.save ,则缓存不会更新更新通话。

这里缺少什么?

最佳答案

选项 1:使用建议排序,

引用: https://docs.spring.io/spring/docs/current/spring-framework-reference/core.html#aop-ordering

以下声明将导致首先执行事务性建议,然后执行可缓存建议。

<tx:annotation-driven order="0"/>

<cache:annotation-driven cache-manager="ehCacheManager" order="1"/>

选项2:在不同的方法上注解@Cacheable和@Transactional

如果您从另一个使用 @Transactional 注释的方法调用 @Cacheable 注释的方法,您将看到代码正在运行。除非您实现了建议排序,否则同一方法上的两个注释(即 @Cacheable 和 @Transaction)不会对您的事业有帮助。请参阅下面您的逻辑的粗略实现。

    @Override
@Transactional
public Employee customUpdate(Employee employee) {
Employee mergedEmployee = updateHelper(employee);

// rolling back transaction
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();

return mergedEmployee;
}

@Cacheable(cacheNames = "EmployeeCache", key = "#a0.id")
public Employee updateHelper(Employee employee)) {
employee.setFirstName(UUID.randomUUID().toString());
//On a merge(...) call on the entityManager, the returned item is the managed
//instance
return entityManager.merge(employee);
}


关于java - Spring事务感知缓存不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58334223/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com