diff --git a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java index 6e0912a91..4f904ab4c 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultValueOperations.java @@ -26,6 +26,7 @@ import org.springframework.dao.DataAccessException; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.connection.RedisStringCommands.SetOption; import org.springframework.data.redis.core.types.Expiration; +import org.springframework.lang.Nullable; /** * Default implementation of {@link ValueOperations}. @@ -308,6 +309,35 @@ class DefaultValueOperations extends AbstractOperations implements V return execute(connection -> connection.set(rawKey, rawValue, expiration, SetOption.ifAbsent()), true); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.ValueOperations#setIfPresent(java.lang.Object, java.lang.Object) + */ + @Nullable + @Override + public Boolean setIfPresent(K key, V value) { + + byte[] rawKey = rawKey(key); + byte[] rawValue = rawValue(value); + + return execute(connection -> connection.set(rawKey, rawValue, Expiration.persistent(), SetOption.ifPresent()), true); + } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.core.ValueOperations#setIfPresent(java.lang.Object, java.lang.Object, long, java.util.concurrent.TimeUnit) + */ + @Nullable + @Override + public Boolean setIfPresent(K key, V value, long timeout, TimeUnit unit) { + + byte[] rawKey = rawKey(key); + byte[] rawValue = rawValue(value); + + Expiration expiration = Expiration.from(timeout, unit); + return execute(connection -> connection.set(rawKey, rawValue, expiration, SetOption.ifPresent()), true); + } + /* * (non-Javadoc) * @see org.springframework.data.redis.core.ValueOperations#set(java.lang.Object, java.lang.Object, long) diff --git a/src/main/java/org/springframework/data/redis/core/ValueOperations.java b/src/main/java/org/springframework/data/redis/core/ValueOperations.java index 93e83b70a..200e6b5f5 100644 --- a/src/main/java/org/springframework/data/redis/core/ValueOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ValueOperations.java @@ -77,6 +77,29 @@ public interface ValueOperations { @Nullable Boolean setIfAbsent(K key, V value, long timeout, TimeUnit unit); + /** + * Set {@code key} to hold the string {@code value} if {@code key} is present. + * + * @param key must not be {@literal null}. + * @param value + * @since 2.1 + * @see Redis Documentation: SET + */ + @Nullable + Boolean setIfPresent(K key, V value); + + /** + * Set {@code key} to hold the string {@code value} and expiration {@code timeout} if {@code key} is present. + * + * @param key must not be {@literal null}. + * @param value + * @param timeout must not be {@literal null}. + * @since 2.1 + * @see Redis Documentation: SET + */ + @Nullable + Boolean setIfPresent(K key, V value, long timeout, TimeUnit unit); + /** * Set multiple keys to multiple values using key-value pairs provided in {@code tuple}. * diff --git a/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java b/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java index 5659e439c..d2786e59c 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultValueOperationsTests.java @@ -281,6 +281,38 @@ public class DefaultValueOperationsTests { assertThat(expire, is(greaterThan(TimeUnit.MILLISECONDS.toMillis(1)))); } + @Test // DATAREDIS-786 + public void testSetIfPresent() { + + K key = keyFactory.instance(); + V value1 = valueFactory.instance(); + V value2 = valueFactory.instance(); + + assertFalse(valueOps.setIfPresent(key, value1)); + valueOps.set(key, value1); + + assertTrue(valueOps.setIfPresent(key, value2)); + assertThat(valueOps.get(key), is(value2)); + } + + @Test // DATAREDIS-786 + public void testSetIfPresentWithExpiration() { + + K key = keyFactory.instance(); + V value1 = valueFactory.instance(); + V value2 = valueFactory.instance(); + + assertFalse(valueOps.setIfPresent(key, value1, 5, TimeUnit.SECONDS)); + valueOps.set(key, value1); + + assertTrue(valueOps.setIfPresent(key, value2, 5, TimeUnit.SECONDS)); + + Long expire = redisTemplate.getExpire(key, TimeUnit.MILLISECONDS); + assertThat(expire, is(lessThan(TimeUnit.SECONDS.toMillis(6)))); + assertThat(expire, is(greaterThan(TimeUnit.MILLISECONDS.toMillis(1)))); + assertThat(valueOps.get(key), is(value2)); + } + @Test public void testSize() { K key1 = keyFactory.instance();