Introduce evictIfPresent/invalidate operations on Cache abstraction
@CacheEvict.beforeInvocation suggests immediate execution even in case of transactional caches. The cache interceptor delegates to the new evictIfPresent/invalidate operations now which imply immediate execution semantics (and also provide an indication for whether any corresponding entries where present when programmatically called). Closes gh-23192
This commit is contained in:
@@ -21,25 +21,23 @@ import org.junit.Test;
|
||||
import org.springframework.cache.Cache;
|
||||
import org.springframework.cache.concurrent.ConcurrentMapCache;
|
||||
import org.springframework.tests.transaction.CallCountingTransactionManager;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionStatus;
|
||||
import org.springframework.transaction.interceptor.DefaultTransactionAttribute;
|
||||
import org.springframework.transaction.support.TransactionTemplate;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
|
||||
|
||||
/**
|
||||
* @author Stephane Nicoll
|
||||
* @author Juergen Hoeller
|
||||
*/
|
||||
public class TransactionAwareCacheDecoratorTests {
|
||||
|
||||
private final PlatformTransactionManager txManager = new CallCountingTransactionManager();
|
||||
private final TransactionTemplate txTemplate = new TransactionTemplate(new CallCountingTransactionManager());
|
||||
|
||||
|
||||
@Test
|
||||
public void createWithNullTarget() {
|
||||
assertThatIllegalArgumentException().isThrownBy(() ->
|
||||
new TransactionAwareCacheDecorator(null));
|
||||
assertThatIllegalArgumentException().isThrownBy(() -> new TransactionAwareCacheDecorator(null));
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -79,20 +77,18 @@ public class TransactionAwareCacheDecoratorTests {
|
||||
public void putTransactional() {
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
|
||||
TransactionStatus status = this.txManager.getTransaction(
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
assertThat(target.get(key)).isNull();
|
||||
this.txManager.commit(status);
|
||||
|
||||
txTemplate.execute(() -> {
|
||||
cache.put(key, "123");
|
||||
assertThat(target.get(key)).isNull();
|
||||
});
|
||||
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putIfAbsent() { // no transactional support for putIfAbsent
|
||||
public void putIfAbsentNonTransactional() {
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
|
||||
@@ -104,6 +100,23 @@ public class TransactionAwareCacheDecoratorTests {
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void putIfAbsentTransactional() { // no transactional support for putIfAbsent
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
Object key = new Object();
|
||||
|
||||
txTemplate.execute(() -> {
|
||||
assertThat(cache.putIfAbsent(key, "123")).isNull();
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
assertThat(cache.putIfAbsent(key, "456").get()).isEqualTo("123");
|
||||
// unchanged
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
});
|
||||
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictNonTransactional() {
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
@@ -122,12 +135,36 @@ public class TransactionAwareCacheDecoratorTests {
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
txTemplate.execute(() -> {
|
||||
cache.evict(key);
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
});
|
||||
|
||||
TransactionStatus status = this.txManager.getTransaction(
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
cache.evict(key);
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
this.txManager.commit(status);
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictIfPresentNonTransactional() {
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
cache.evictIfPresent(key);
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void evictIfPresentTransactional() { // no transactional support for evictIfPresent
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
txTemplate.execute(() -> {
|
||||
cache.evictIfPresent(key);
|
||||
assertThat(target.get(key)).isNull();
|
||||
});
|
||||
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
@@ -150,13 +187,38 @@ public class TransactionAwareCacheDecoratorTests {
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
|
||||
TransactionStatus status = this.txManager.getTransaction(
|
||||
new DefaultTransactionAttribute(TransactionDefinition.PROPAGATION_REQUIRED));
|
||||
cache.clear();
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
this.txManager.commit(status);
|
||||
txTemplate.execute(() -> {
|
||||
cache.clear();
|
||||
assertThat(target.get(key, String.class)).isEqualTo("123");
|
||||
});
|
||||
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidateNonTransactional() {
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
cache.invalidate();
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void invalidateTransactional() { // no transactional support for invalidate
|
||||
Cache target = new ConcurrentMapCache("testCache");
|
||||
Cache cache = new TransactionAwareCacheDecorator(target);
|
||||
Object key = new Object();
|
||||
cache.put(key, "123");
|
||||
|
||||
txTemplate.execute(() -> {
|
||||
cache.invalidate();
|
||||
assertThat(target.get(key)).isNull();
|
||||
});
|
||||
|
||||
assertThat(target.get(key)).isNull();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user