diff --git a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java index 55d7dd9de..43500a5e4 100644 --- a/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/BoundHashOperations.java @@ -33,6 +33,8 @@ public interface BoundHashOperations extends BoundKeyOperations { Long increment(HK key, long delta); + Double increment(HK key, double delta); + HV get(Object key); void put(HK key, HV value); diff --git a/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java index d188109fc..69237311f 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultBoundHashOperations.java @@ -72,7 +72,10 @@ class DefaultBoundHashOperations extends DefaultBoundKeyOperations return ops.increment(getKey(), key, delta); } - + public Double increment(HK key, double delta) { + return ops.increment(getKey(), key, delta); + } + public Set keys() { return ops.keys(getKey()); } diff --git a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java index 86ac353a5..5c36776bb 100644 --- a/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/DefaultHashOperations.java @@ -79,7 +79,17 @@ class DefaultHashOperations extends AbstractOperations imp } - + public Double increment(K key, HK hashKey, final double delta) { + final byte[] rawKey = rawKey(key); + final byte[] rawHashKey = rawHashKey(hashKey); + + return execute(new RedisCallback() { + public Double doInRedis(RedisConnection connection) { + return connection.hIncrBy(rawKey, rawHashKey, delta); + } + }, true); + } + public Set keys(K key) { final byte[] rawKey = rawKey(key); diff --git a/src/main/java/org/springframework/data/redis/core/HashOperations.java b/src/main/java/org/springframework/data/redis/core/HashOperations.java index c82d9ce2b..790c30f82 100644 --- a/src/main/java/org/springframework/data/redis/core/HashOperations.java +++ b/src/main/java/org/springframework/data/redis/core/HashOperations.java @@ -37,6 +37,8 @@ public interface HashOperations { Long increment(H key, HK hashKey, long delta); + Double increment(H key, HK hashKey, double delta); + Set keys(H key); Long size(H key); diff --git a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java index 3aae0381c..8c5cef921 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java +++ b/src/main/java/org/springframework/data/redis/support/collections/DefaultRedisMap.java @@ -89,7 +89,11 @@ public class DefaultRedisMap implements RedisMap { public Long increment(K key, long delta) { return hashOps.increment(key, delta); } - + + public Double increment(K key, double delta) { + return hashOps.increment(key, delta); + } + public RedisOperations getOperations() { return hashOps.getOperations(); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java b/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java index b32636e83..67c5c0ce7 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisMap.java @@ -26,4 +26,6 @@ import java.util.concurrent.ConcurrentMap; public interface RedisMap extends RedisStore, ConcurrentMap { Long increment(K key, long delta); + + Double increment(K key, double delta); } diff --git a/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java b/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java index a1fcc0f02..277bb0ec0 100644 --- a/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java +++ b/src/main/java/org/springframework/data/redis/support/collections/RedisProperties.java @@ -23,7 +23,6 @@ import java.util.Date; import java.util.Enumeration; import java.util.LinkedHashSet; import java.util.Map; -import java.util.Map.Entry; import java.util.Properties; import java.util.Set; import java.util.concurrent.TimeUnit; @@ -209,8 +208,11 @@ public class RedisProperties extends Properties implements RedisMap getOperations() { return hashOps.getOperations(); } diff --git a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapTests.java b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapTests.java index ca6b3d995..07bf2e173 100644 --- a/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapTests.java +++ b/src/test/java/org/springframework/data/redis/support/collections/AbstractRedisMapTests.java @@ -51,6 +51,7 @@ import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.RedisCallback; import org.springframework.data.redis.core.RedisOperations; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.test.annotation.IfProfileValue; /** * Integration test for Redis Map. @@ -194,8 +195,9 @@ public abstract class AbstractRedisMapTests { } @Test - public void testIncrement() { - assumeTrue(!ConnectionUtils.isJredis(template.getConnectionFactory())); + public void testIncrementNotNumber() { + assumeTrue(!ConnectionUtils.isJredis(template.getConnectionFactory()) && + !(valueFactory instanceof LongObjectFactory)); K k1 = getKey(); V v1 = getValue(); @@ -210,6 +212,25 @@ public abstract class AbstractRedisMapTests { } } + @Test + public void testIncrement() { + assumeTrue(valueFactory instanceof LongObjectFactory); + K k1 = getKey(); + V v1 = getValue(); + map.put(k1, v1); + assertEquals(Long.valueOf(Long.valueOf((String)v1) + 10), map.increment(k1, 10)); + } + + @IfProfileValue(name = "redisVersion", value = "2.6") + @Test + public void testIncrementDouble() { + assumeTrue(valueFactory instanceof DoubleObjectFactory); + K k1 = getKey(); + V v1 = getValue(); + map.put(k1, v1); + assertEquals(Double.valueOf(Double.valueOf((String)v1) + 3.4), map.increment(k1, 3.4)); + } + @Test public void testIsEmpty() { map.clear(); diff --git a/src/test/java/org/springframework/data/redis/support/collections/DoubleObjectFactory.java b/src/test/java/org/springframework/data/redis/support/collections/DoubleObjectFactory.java new file mode 100644 index 000000000..72dcb7ade --- /dev/null +++ b/src/test/java/org/springframework/data/redis/support/collections/DoubleObjectFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.support.collections; + +import java.util.Random; + +/** + * + * Implementation of {@link ObjectFactory that returns random Doubles as Strings + * @author Jennifer Hickey + * + */ +public class DoubleObjectFactory implements ObjectFactory { + + private Random random = new Random(System.currentTimeMillis()); + + public String instance() { + return String.valueOf(random.nextDouble()); + } + +} diff --git a/src/test/java/org/springframework/data/redis/support/collections/LongObjectFactory.java b/src/test/java/org/springframework/data/redis/support/collections/LongObjectFactory.java new file mode 100644 index 000000000..d1838551d --- /dev/null +++ b/src/test/java/org/springframework/data/redis/support/collections/LongObjectFactory.java @@ -0,0 +1,34 @@ +/* + * Copyright 2013 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package org.springframework.data.redis.support.collections; + +import java.util.Random; + +/** +* +* Implementation of {@link ObjectFactory that returns random Longs as Strings +* @author Jennifer Hickey +* +*/ +public class LongObjectFactory implements ObjectFactory { + + private Random random = new Random(System.currentTimeMillis()); + + public String instance() { + return String.valueOf(random.nextLong()); + } + +} diff --git a/src/test/java/org/springframework/data/redis/support/collections/RedisMapTests.java b/src/test/java/org/springframework/data/redis/support/collections/RedisMapTests.java index f16a89cd3..643972c90 100644 --- a/src/test/java/org/springframework/data/redis/support/collections/RedisMapTests.java +++ b/src/test/java/org/springframework/data/redis/support/collections/RedisMapTests.java @@ -27,8 +27,10 @@ import org.springframework.data.redis.connection.jredis.JredisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; import org.springframework.data.redis.connection.srp.SrpConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.JacksonJsonRedisSerializer; import org.springframework.data.redis.serializer.OxmSerializer; +import org.springframework.data.redis.serializer.StringRedisSerializer; import org.springframework.oxm.xstream.XStreamMarshaller; /** @@ -65,6 +67,8 @@ public class RedisMapTests extends AbstractRedisMapTests { // create Jedis Factory ObjectFactory stringFactory = new StringObjectFactory(); ObjectFactory personFactory = new PersonObjectFactory(); + ObjectFactory doubleFactory = new DoubleObjectFactory(); + ObjectFactory longFactory = new LongObjectFactory(); JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory(); jedisConnFactory.setUsePool(true); @@ -131,6 +135,10 @@ public class RedisMapTests extends AbstractRedisMapTests { jsonPersonTemplateLettuce.setHashValueSerializer(jsonStringSerializer); jsonPersonTemplateLettuce.afterPropertiesSet(); + RedisTemplate stringTemplateLtc = new StringRedisTemplate(); + stringTemplateLtc.setConnectionFactory(lettuceConnFactory); + stringTemplateLtc.afterPropertiesSet(); + // SRP SrpConnectionFactory srpConnFactory = new SrpConnectionFactory(); srpConnFactory.setPort(SettingsUtils.getPort()); @@ -153,6 +161,10 @@ public class RedisMapTests extends AbstractRedisMapTests { jsonPersonTemplateSrp.setHashValueSerializer(jsonStringSerializer); jsonPersonTemplateSrp.afterPropertiesSet(); + RedisTemplate stringTemplateSrp = new StringRedisTemplate(); + stringTemplateSrp.setConnectionFactory(srpConnFactory); + stringTemplateSrp.afterPropertiesSet(); + return Arrays.asList(new Object[][] { { stringFactory, stringFactory, genericTemplate }, @@ -173,11 +185,15 @@ public class RedisMapTests extends AbstractRedisMapTests { { personFactory, stringFactory, genericTemplateLettuce }, { personFactory, stringFactory, xGenericTemplateLettuce }, { personFactory, stringFactory, jsonPersonTemplateLettuce }, + { stringFactory, doubleFactory, stringTemplateLtc}, + { stringFactory, longFactory, stringTemplateLtc}, { stringFactory, stringFactory, genericTemplateSrp }, { personFactory, personFactory, genericTemplateSrp }, { stringFactory, personFactory, genericTemplateSrp }, { personFactory, stringFactory, genericTemplateSrp }, { personFactory, stringFactory, xGenericTemplateSrp }, + { stringFactory, doubleFactory, stringTemplateSrp}, + { stringFactory, longFactory, stringTemplateSrp}, { personFactory, stringFactory, jsonPersonTemplateSrp }}); } } \ No newline at end of file diff --git a/src/test/java/org/springframework/data/redis/support/collections/RedisPropertiesTests.java b/src/test/java/org/springframework/data/redis/support/collections/RedisPropertiesTests.java index 2455f1841..87cdb18d8 100644 --- a/src/test/java/org/springframework/data/redis/support/collections/RedisPropertiesTests.java +++ b/src/test/java/org/springframework/data/redis/support/collections/RedisPropertiesTests.java @@ -41,6 +41,7 @@ import org.springframework.data.redis.connection.jedis.JedisConnectionFactory; import org.springframework.data.redis.connection.jredis.DefaultJredisPool; import org.springframework.data.redis.connection.jredis.JredisConnectionFactory; import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory; +import org.springframework.data.redis.connection.srp.SrpConnectionFactory; import org.springframework.data.redis.core.RedisTemplate; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.data.redis.serializer.JacksonJsonRedisSerializer; @@ -235,6 +236,8 @@ public class RedisPropertiesTests extends RedisMapTests { // create Jedis Factory ObjectFactory stringFactory = new StringObjectFactory(); + ObjectFactory longFactory = new LongObjectFactory(); + ObjectFactory doubleFactory = new DoubleObjectFactory(); JedisConnectionFactory jedisConnFactory = new JedisConnectionFactory(); jedisConnFactory.setUsePool(true); @@ -296,9 +299,29 @@ public class RedisPropertiesTests extends RedisMapTests { jsonPersonTemplateLtc.setHashValueSerializer(jsonStringSerializer); jsonPersonTemplateLtc.afterPropertiesSet(); + // SRP + SrpConnectionFactory srpConnFactory = new SrpConnectionFactory(); + srpConnFactory.setPort(SettingsUtils.getPort()); + srpConnFactory.setHostName(SettingsUtils.getHost()); + srpConnFactory.afterPropertiesSet(); + + RedisTemplate genericTemplateSrp = new StringRedisTemplate(srpConnFactory); + RedisTemplate xGenericTemplateSrp = new RedisTemplate(); + xGenericTemplateSrp.setConnectionFactory(srpConnFactory); + xGenericTemplateSrp.setDefaultSerializer(serializer); + xGenericTemplateSrp.afterPropertiesSet(); + + RedisTemplate jsonPersonTemplateSrp = new RedisTemplate(); + jsonPersonTemplateSrp.setConnectionFactory(srpConnFactory); + jsonPersonTemplateSrp.setDefaultSerializer(jsonSerializer); + jsonPersonTemplateSrp.setHashKeySerializer(jsonSerializer); + jsonPersonTemplateSrp.setHashValueSerializer(jsonStringSerializer); + jsonPersonTemplateSrp.afterPropertiesSet(); + return Arrays.asList(new Object[][] { { stringFactory, stringFactory, genericTemplate }, - { stringFactory, stringFactory, genericTemplate }, { stringFactory, stringFactory, genericTemplate }, + { stringFactory, stringFactory, genericTemplate }, + { stringFactory, stringFactory, genericTemplate }, { stringFactory, stringFactory, genericTemplate }, { stringFactory, stringFactory, xstreamGenericTemplate }, { stringFactory, stringFactory, genericTemplateJR }, @@ -312,7 +335,17 @@ public class RedisPropertiesTests extends RedisMapTests { { stringFactory, stringFactory, genericTemplateLtc }, { stringFactory, stringFactory, genericTemplateLtc }, { stringFactory, stringFactory, genericTemplateLtc }, + { stringFactory, doubleFactory, genericTemplateLtc }, + { stringFactory, longFactory, genericTemplateLtc }, { stringFactory, stringFactory, xGenericTemplateLtc }, - { stringFactory, stringFactory, jsonPersonTemplateLtc }}); + { stringFactory, stringFactory, jsonPersonTemplateLtc }, + { stringFactory, stringFactory, genericTemplateSrp }, + { stringFactory, stringFactory, genericTemplateSrp }, + { stringFactory, stringFactory, genericTemplateSrp }, + { stringFactory, stringFactory, genericTemplateSrp }, + { stringFactory, doubleFactory, genericTemplateSrp }, + { stringFactory, longFactory, genericTemplateSrp }, + { stringFactory, stringFactory, xGenericTemplateSrp }, + { stringFactory, stringFactory, jsonPersonTemplateSrp }}); } } \ No newline at end of file