diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index 97f25e336..7987ce831 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -505,8 +505,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return result; } - public Long lPush(byte[] key, byte[] value) { - Long result = delegate.lPush(key, value); + public Long lPush(byte[] key, byte[]... values) { + Long result = delegate.lPush(key, values); if(isFutureConversion()) { addResultConverter(identityConverter); } @@ -1525,8 +1525,8 @@ public class DefaultStringRedisConnection implements StringRedisConnection { } - public Long lPush(String key, String value) { - Long result = delegate.lPush(serialize(key), serialize(value)); + public Long lPush(String key, String... values) { + Long result = delegate.lPush(serialize(key), serializeMulti(values)); if(isFutureConversion()) { addResultConverter(identityConverter); } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java index 7b1d79d1e..0a36acee2 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisListCommands.java @@ -34,7 +34,7 @@ public interface RedisListCommands { Long rPush(byte[] key, byte[] value); - Long lPush(byte[] key, byte[] value); + Long lPush(byte[] key, byte[]... value); Long rPushX(byte[] key, byte[] value); diff --git a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java index 347c343b0..895a45e64 100644 --- a/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/StringRedisConnection.java @@ -127,7 +127,7 @@ public interface StringRedisConnection extends RedisConnection { Long rPush(String key, String value); - Long lPush(String key, String value); + Long lPush(String key, String... values); Long rPushX(String key, String value); diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index 8e293bf71..792049286 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -1322,17 +1322,21 @@ public class JedisConnection implements RedisConnection { // List commands // - public Long lPush(byte[] key, byte[] value) { + public Long lPush(byte[] key, byte[]... values) { + if((isPipelined() || isQueueing()) && values.length > 1) { + throw new UnsupportedOperationException("lPush of multiple fields not supported " + + "in pipeline or transaction"); + } try { if (isPipelined()) { - pipeline(new JedisResult(pipeline.lpush(key, value))); + pipeline(new JedisResult(pipeline.lpush(key, values[0]))); return null; } if (isQueueing()) { - transaction(new JedisResult(transaction.lpush(key, value))); + transaction(new JedisResult(transaction.lpush(key, values[0]))); return null; } - return jedis.lpush(key, value); + return jedis.lpush(key, values); } catch (Exception ex) { throw convertJedisAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java index f158b4ceb..76d518eaa 100644 --- a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java @@ -678,9 +678,12 @@ public class JredisConnection implements RedisConnection { } - public Long lPush(byte[] key, byte[] value) { + public Long lPush(byte[] key, byte[]... values) { + if(values.length > 1) { + throw new UnsupportedOperationException("lPush of multiple fields not supported"); + } try { - jredis.lpush(key, value); + jredis.lpush(key, values[0]); return null; } catch (Exception ex) { throw convertJredisAccessException(ex); diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index 440d0f5a6..d3a722193 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -1421,17 +1421,17 @@ public class LettuceConnection implements RedisConnection { // - public Long lPush(byte[] key, byte[] value) { + public Long lPush(byte[] key, byte[]... values) { try { if (isPipelined()) { - pipeline(new LettuceResult(getAsyncConnection().lpush(key, value))); + pipeline(new LettuceResult(getAsyncConnection().lpush(key, values))); return null; } if (isQueueing()) { - transaction(new LettuceTxResult(getConnection().lpush(key, value))); + transaction(new LettuceTxResult(getConnection().lpush(key, values))); return null; } - return getConnection().lpush(key, value); + return getConnection().lpush(key, values); } catch (Exception ex) { throw convertLettuceAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java index c98ed8201..51ff10ad3 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java @@ -1106,13 +1106,13 @@ public class SrpConnection implements RedisConnection { // List commands // - public Long lPush(byte[] key, byte[] value) { + public Long lPush(byte[] key, byte[]... values) { try { if (isPipelined()) { - pipeline(new SrpResult(pipeline.lpush(key, new Object[] { value }))); + pipeline(new SrpResult(pipeline.lpush(key, (Object[]) values))); return null; } - return client.lpush(key, new Object[] { value }).data(); + return client.lpush(key, (Object[]) values ).data(); } catch (Exception ex) { throw convertSrpAccessException(ex); } diff --git a/src/main/java/org/springframework/data/redis/core/AbstractOperations.java b/src/main/java/org/springframework/data/redis/core/AbstractOperations.java index 60b5e36a1..1824dad11 100644 --- a/src/main/java/org/springframework/data/redis/core/AbstractOperations.java +++ b/src/main/java/org/springframework/data/redis/core/AbstractOperations.java @@ -111,6 +111,15 @@ abstract class AbstractOperations { return valueSerializer().serialize(value); } + byte[][] rawValues(Object... values) { + final byte[][] rawValues = new byte[values.length][]; + int i = 0; + for (Object value : values) { + rawValues[i++] = rawValue(value); + } + return rawValues; + } + @SuppressWarnings("unchecked") byte[] rawHashKey(HK hashKey) { Assert.notNull(hashKey, "non null hash key required"); diff --git a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java index 843421a84..f35520a21 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundListOperations.java @@ -35,6 +35,8 @@ public interface BoundListOperations extends BoundKeyOperations { Long leftPush(V value); + Long leftPushAll(V... values); + Long leftPushIfPresent(V value); Long leftPush(V pivot, V value); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java index 5f553afba..ca26c6622 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundListOperations.java @@ -67,6 +67,9 @@ class DefaultBoundListOperations extends DefaultBoundKeyOperations impl return ops.leftPush(getKey(), value); } + public Long leftPushAll(V... values) { + return ops.leftPushAll(getKey(), values); + } public Long leftPushIfPresent(V value) { return ops.leftPushIfPresent(getKey(), value); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultListOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultListOperations.java index 41a6a39cf..181e0a58a 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultListOperations.java @@ -76,7 +76,16 @@ class DefaultListOperations extends AbstractOperations implements Li }, true); } - + public Long leftPushAll(K key, V... values) { + final byte[] rawKey = rawKey(key); + final byte[][] rawValues = rawValues(values); + return execute(new RedisCallback() { + public Long doInRedis(RedisConnection connection) { + return connection.lPush(rawKey, rawValues); + } + }, true); + } + public Long leftPushIfPresent(K key, V value) { final byte[] rawKey = rawKey(key); final byte[] rawValue = rawValue(value); diff --git a/src/main/java/org/springframework/data/redis/core/ListOperations.java b/src/main/java/org/springframework/data/redis/core/ListOperations.java index 94536798a..8048b4c40 100644 --- a/src/main/java/org/springframework/data/redis/core/ListOperations.java +++ b/src/main/java/org/springframework/data/redis/core/ListOperations.java @@ -33,6 +33,8 @@ public interface ListOperations { Long leftPush(K key, V value); + Long leftPushAll(K key, V... values); + Long leftPushIfPresent(K key, V value); Long leftPush(K key, V pivot, V value); diff --git a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java index fdd124d7c..ff741e006 100644 --- a/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/AbstractConnectionIntegrationTests.java @@ -1259,6 +1259,14 @@ public abstract class AbstractConnectionIntegrationTests { Arrays.asList(new String[] { "baz", "bar" }) })); } + @Test + public void testLPushMultiple() { + actual.add(connection.lPush("testlist", "bar", "baz")); + actual.add(connection.lRange("testlist", 0, -1)); + verifyResults(Arrays.asList(new Object[] { 2l, + Arrays.asList(new String[] { "baz", "bar" }) })); + } + // Set operations @Test diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java index 80684396e..ee31653ef 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionPipelineIntegrationTests.java @@ -431,4 +431,9 @@ public class JedisConnectionPipelineIntegrationTests extends public void testHDelMultiple() { super.testHDelMultiple(); } + + @Test(expected=UnsupportedOperationException.class) + public void testLPushMultiple() { + super.testLPushMultiple(); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionTransactionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionTransactionIntegrationTests.java index b1155d22d..08615fa4c 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionTransactionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionTransactionIntegrationTests.java @@ -367,4 +367,9 @@ public class JedisConnectionTransactionIntegrationTests extends public void testHDelMultiple() { super.testHDelMultiple(); } + + @Test(expected=UnsupportedOperationException.class) + public void testLPushMultiple() { + super.testLPushMultiple(); + } } diff --git a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java index d8d1bb1ed..e53b2e02a 100644 --- a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionIntegrationTests.java @@ -565,6 +565,11 @@ public class JRedisConnectionIntegrationTests extends AbstractConnectionIntegrat super.testHDelMultiple(); } + @Test(expected=UnsupportedOperationException.class) + public void testLPushMultiple() { + super.testLPushMultiple(); + } + // Jredis returns null for rPush and lPush @Test public void testLLen() { diff --git a/src/test/java/org/springframework/data/redis/core/DefaultListOperationsTests.java b/src/test/java/org/springframework/data/redis/core/DefaultListOperationsTests.java index 6ca336524..85ef6ce94 100644 --- a/src/test/java/org/springframework/data/redis/core/DefaultListOperationsTests.java +++ b/src/test/java/org/springframework/data/redis/core/DefaultListOperationsTests.java @@ -106,6 +106,18 @@ public class DefaultListOperationsTests { assertThat(listOps.range(key, 0, -1), isEqual(Arrays.asList(new Object[] {v2, v1}))); } + @SuppressWarnings("unchecked") + @Test + public void testLeftPushAll() { + K key = keyFactory.instance(); + V v1 = valueFactory.instance(); + V v2 = valueFactory.instance(); + V v3 = valueFactory.instance(); + assertEquals(Long.valueOf(2),listOps.leftPushAll(key, v1, v2)); + assertEquals(Long.valueOf(3), listOps.leftPush(key, v3)); + assertThat(listOps.range(key, 0, -1), isEqual(Arrays.asList(new Object[] {v3, v2, v1}))); + } + @Test public void testRightPopAndLeftPushTimeout() { // 1 ms timeout gets upgraded to 1 sec timeout at the moment