diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundHashOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundHashOperations.java index b0f71960d..19ddc0966 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundHashOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/BoundHashOperations.java @@ -34,6 +34,8 @@ public interface BoundHashOperations extends KeyBound { void set(HK key, HV value); + Collection multiGet(Set keys); + void multiSet(Map m); Set keys(); @@ -43,4 +45,5 @@ public interface BoundHashOperations extends KeyBound { Integer length(); void delete(Object key); + } diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundHashOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundHashOperations.java index 8387c45be..c7870393c 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundHashOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/DefaultBoundHashOperations.java @@ -49,6 +49,11 @@ class DefaultBoundHashOperations extends DefaultKeyBound implement return ops.get(getKey(), key); } + @Override + public Collection multiGet(Set hashKeys) { + return ops.multiGet(getKey(), hashKeys); + } + @Override public RedisOperations getOperations() { return ops.getOperations(); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/HashOperations.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/HashOperations.java index 23755be71..213d4550d 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/HashOperations.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/HashOperations.java @@ -32,6 +32,8 @@ public interface HashOperations { HV get(H key, Object hashKey); + Collection multiGet(H key, Set hashKeys); + Integer increment(H key, HK hashKey, int delta); Set keys(H key); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java index 260a02968..29b1b5336 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/core/RedisTemplate.java @@ -21,6 +21,7 @@ import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; @@ -960,7 +961,7 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation } }, true); - return (HV) deserializeHashValue(rawHashValue); + return RedisTemplate.this. deserializeHashValue(rawHashValue); } @Override @@ -1039,6 +1040,32 @@ public class RedisTemplate extends RedisAccessor implements RedisOperation }, true); } + + @Override + public Collection multiGet(K key, Set fields) { + if (fields.isEmpty()) { + return Collections.emptyList(); + } + + final byte[] rawKey = rawKey(key); + + final byte[][] rawHashKeys = new byte[fields.size()][]; + + int counter = 0; + for (HK hashKey : fields) { + rawHashKeys[counter++] = rawHashKey(hashKey); + } + + List rawValues = execute(new RedisCallback>() { + @Override + public List doInRedis(RedisConnection connection) { + return connection.hMGet(rawKey, rawHashKeys); + } + }, true); + + return (List) hashValues(rawValues, List.class); + } + @Override public void set(K key, HK hashKey, HV value) { final byte[] rawKey = rawKey(key); diff --git a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisMap.java b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisMap.java index ff580c50b..6b18ae8f7 100644 --- a/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisMap.java +++ b/spring-data-redis/src/main/java/org/springframework/data/keyvalue/redis/util/DefaultRedisMap.java @@ -16,6 +16,8 @@ package org.springframework.data.keyvalue.redis.util; import java.util.Collection; +import java.util.Iterator; +import java.util.LinkedHashSet; import java.util.Map; import java.util.Set; @@ -31,6 +33,32 @@ public class DefaultRedisMap implements RedisMap { private final BoundHashOperations hashOps; + private class DefaultRedisMapEntry implements Map.Entry { + + private K key; + private V value; + + public DefaultRedisMapEntry(K key, V value) { + this.key = key; + this.value = value; + } + + @Override + public K getKey() { + return key; + } + + @Override + public V getValue() { + return value; + } + + @Override + public V setValue(V value) { + throw new UnsupportedOperationException(); + } + } + /** * Constructs a new DefaultRedisMap instance. * @@ -91,7 +119,18 @@ public class DefaultRedisMap implements RedisMap { @Override public Set> entrySet() { - throw new UnsupportedOperationException(); + Set keySet = keySet(); + Collection multiGet = hashOps.multiGet(keySet); + + Iterator keys = keySet.iterator(); + Iterator values = multiGet.iterator(); + + Set> entries = new LinkedHashSet>(); + while (keys.hasNext()) { + entries.add(new DefaultRedisMapEntry(keys.next(), values.next())); + } + + return entries; } @Override diff --git a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisMapTests.java b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisMapTests.java index 5ad668e4f..3a5d210b8 100644 --- a/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisMapTests.java +++ b/spring-data-redis/src/test/java/org/springframework/data/keyvalue/redis/util/AbstractRedisMapTests.java @@ -19,6 +19,7 @@ import static org.hamcrest.CoreMatchers.*; import static org.junit.Assert.*; import static org.junit.matchers.JUnitMatchers.*; +import java.util.ArrayList; import java.util.Collection; import java.util.Iterator; import java.util.LinkedHashMap; @@ -344,8 +345,34 @@ public abstract class AbstractRedisMapTests { assertThat(values, hasItems(v1, v2, v3)); } - @Test(expected = UnsupportedOperationException.class) + @Test public void testEntrySet() { - map.entrySet(); + Set> entries = map.entrySet(); + assertTrue(entries.isEmpty()); + + K k1 = getKey(); + K k2 = getKey(); + + V v1 = getValue(); + V v2 = getValue(); + + map.put(k1, v1); + map.put(k2, v1); + + entries = map.entrySet(); + + Set keys = new LinkedHashSet(); + Collection values = new ArrayList(); + + for (Entry entry : entries) { + keys.add(entry.getKey()); + values.add(entry.getValue()); + } + + assertEquals(2, keys.size()); + + assertThat(keys, hasItems(k1, k2)); + assertThat(values, hasItem(v1)); + assertThat(values, not(hasItem(v2))); } } \ No newline at end of file