diff --git a/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java b/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java index e239b96d1ee16ca686155d5fdf64106b88030cca..4c5a7fdb1748cf1aaeb63fbe2b4e23d2f0c12ba3 100644 --- a/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java +++ b/spring-context-support/src/main/java/org/springframework/cache/transaction/TransactionAwareCacheDecorator.java @@ -22,17 +22,18 @@ import org.springframework.transaction.support.TransactionSynchronizationManager import org.springframework.util.Assert; /** - * Cache decorator which synchronizes its {@link #put} and {@link #evict} operations with - * Spring-managed transactions (through Spring's {@link TransactionSynchronizationManager}, - * performing the actual cache put/evict operation only in the after-commit phase of a - * successful transaction. If no transaction is active, {@link #put} and {@link #evict} - * operations will be performed immediately, as usual. + * Cache decorator which synchronizes its {@link #put}, {@link #evict} and {@link #clear} + * operations with Spring-managed transactions (through Spring's {@link TransactionSynchronizationManager}, + * performing the actual cache put/evict/clear operation only in the after-commit phase of a + * successful transaction. If no transaction is active, {@link #put}, {@link #evict} and + * {@link #clear} operations will be performed immediately, as usual. * *

Use of more aggressive operations such as {@link #putIfAbsent} cannot be deferred * to the after-commit phase of a running transaction. Use these with care. * * @author Juergen Hoeller * @author Stephane Nicoll + * @author Stas Volsky * @since 3.2 * @see TransactionAwareCacheManagerProxy */ @@ -108,7 +109,17 @@ public class TransactionAwareCacheDecorator implements Cache { @Override public void clear() { - this.targetCache.clear(); + if (TransactionSynchronizationManager.isSynchronizationActive()) { + TransactionSynchronizationManager.registerSynchronization(new TransactionSynchronizationAdapter() { + @Override + public void afterCommit() { + targetCache.clear(); + } + }); + } + else { + this.targetCache.clear(); + } } } diff --git a/spring-context-support/src/test/java/org/springframework/cache/transaction/TransactionAwareCacheDecoratorTests.java b/spring-context-support/src/test/java/org/springframework/cache/transaction/TransactionAwareCacheDecoratorTests.java index 7b657240bd6815b006605bf6148c711e5520458f..151615db55ac3d76bef96bb35c82468442b3a827 100644 --- a/spring-context-support/src/test/java/org/springframework/cache/transaction/TransactionAwareCacheDecoratorTests.java +++ b/spring-context-support/src/test/java/org/springframework/cache/transaction/TransactionAwareCacheDecoratorTests.java @@ -128,4 +128,31 @@ public class TransactionAwareCacheDecoratorTests { assertNull(target.get(key)); } + @Test + public void clearNonTransactional() { + Cache target = new ConcurrentMapCache("testCache"); + Cache cache = new TransactionAwareCacheDecorator(target); + Object key = new Object(); + cache.put(key, "123"); + + cache.clear(); + assertNull(target.get(key)); + } + + @Test + public void clearTransactional() { + Cache target = new ConcurrentMapCache("testCache"); + Cache cache = new TransactionAwareCacheDecorator(target); + Object key = new Object(); + cache.put(key, "123"); + + + TransactionStatus status = txManager.getTransaction(new DefaultTransactionAttribute( + TransactionDefinition.PROPAGATION_REQUIRED)); + cache.clear(); + assertEquals("123", target.get(key, String.class)); + txManager.commit(status); + + assertNull(target.get(key)); + } }