Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/306.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java Spring事务感知缓存不工作_Java_Spring_Caching_Ehcache - Fatal编程技术网

Java Spring事务感知缓存不工作

Java Spring事务感知缓存不工作,java,spring,caching,ehcache,Java,Spring,Caching,Ehcache,我使用SpringCache抽象,使用Ehcache作为缓存提供程序。 我正在尝试将缓存操作附加到spring JPA事务,但无法这样做 即使事务失败/回滚缓存放置也会发生 配置 @Bean public EhCacheManagerFactoryBean cacheManagerUsingSpringApi() { EhCacheManagerFactoryBean ehCacheManagerFactoryBean = new EhCacheManag

我使用SpringCache抽象,使用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>
测试用例(调用者)

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

因此,如果我用
@CachePut(cacheNames=“EmployeeCache”,key=“#result.id”)
注释
employeeRepository.save
,那么缓存不会在更新调用中更新

这里缺少什么?

选项1:使用建议排序, 参考:

下面的声明将首先执行事务性建议,然后执行可缓存建议

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

<cache:annotation-driven cache-manager="ehCacheManager" order="1"/>
    @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);
}
<tx:annotation-driven order="0"/>

<cache:annotation-driven cache-manager="ehCacheManager" order="1"/>
    @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); 
    }