Merge branch 'cleau-dev'

This commit is contained in:
Costin Leau
2010-11-24 18:43:04 +02:00
56 changed files with 3165 additions and 775 deletions

View File

@@ -13,6 +13,7 @@
<properties>
<jredis.ver>02112010</jredis.ver>
<jedis.ver>1.4.0</jedis.ver>
</properties>
<dependencies>
@@ -96,7 +97,7 @@
<dependency>
<groupId>redis.clients</groupId>
<artifactId>jedis</artifactId>
<version>1.3.1</version>
<version>${jedis.ver}</version>
<scope>compile</scope>
</dependency>

View File

@@ -25,7 +25,7 @@ import org.springframework.datastore.redis.connection.RedisZSetCommands.Tuple;
public class DefaultTuple implements Tuple {
private final Double score;
private final String value;
private final byte[] value;
/**
@@ -34,7 +34,7 @@ public class DefaultTuple implements Tuple {
* @param value
* @param score
*/
public DefaultTuple(String value, Double score) {
public DefaultTuple(byte[] value, Double score) {
this.score = score;
this.value = value;
}
@@ -45,7 +45,7 @@ public class DefaultTuple implements Tuple {
}
@Override
public String getValue() {
public byte[] getValue() {
return value;
}
}

View File

@@ -26,27 +26,27 @@ import java.util.Collection;
public interface RedisCommands extends RedisTxCommands, RedisStringCommands, RedisListCommands, RedisSetCommands,
RedisZSetCommands, RedisHashCommands {
Boolean exists(String key);
Boolean exists(byte[] key);
Integer del(String... keys);
Integer del(byte[]... keys);
DataType type(String key);
DataType type(byte[] key);
Collection<String> keys(String pattern);
Collection<byte[]> keys(byte[] pattern);
String randomKey();
byte[] randomKey();
void rename(String oldName, String newName);
void rename(byte[] oldName, byte[] newName);
Boolean renameNX(String oldName, String newName);
Boolean renameNX(byte[] oldName, byte[] newName);
Integer dbSize();
Boolean expire(String key, int seconds);
Boolean expire(byte[] key, int seconds);
Boolean persist(String key);
Boolean persist(byte[] key);
Integer ttl(String key);
Integer ttl(byte[] key);
void select(int dbIndex);

View File

@@ -37,8 +37,6 @@ public interface RedisConnection extends RedisCommands {
Object getNativeConnection();
String getEncoding();
/**
* Indicates whether the connection is in "queue"(or "MULTI") mode or not.
* When queueing, all commands are postponed until EXEC or DISCARD commands

View File

@@ -17,6 +17,7 @@
package org.springframework.datastore.redis.connection;
import java.util.List;
import java.util.Map;
import java.util.Set;
/**
@@ -26,33 +27,27 @@ import java.util.Set;
*/
public interface RedisHashCommands {
public interface Entry {
public String getField();
Boolean hSet(byte[] key, byte[] field, byte[] value);
public String getValue();
}
Boolean hSetNX(byte[] key, byte[] field, byte[] value);
Boolean hSet(String key, String field, String value);
byte[] hGet(byte[] key, byte[] field);
Boolean hSetNX(String key, String field, String value);
List<byte[]> hMGet(byte[] key, byte[]... fields);
String hGet(String key, String field);
void hMSet(byte[] key, Map<byte[], byte[]> hashes);
List<String> hMGet(String key, String... fields);
Integer hIncrBy(byte[] key, byte[] field, int delta);
void hMSet(String key, String[] fields, String[] values);
Boolean hExists(byte[] key, byte[] field);
Integer hIncrBy(String key, String field, int delta);
Boolean hDel(byte[] key, byte[] field);
Boolean hExists(String key, String field);
Integer hLen(byte[] key);
Boolean hDel(String key, String field);
Set<byte[]> hKeys(byte[] key);
Integer hLen(String key);
List<byte[]> hVals(byte[] key);
Set<String> hKeys(String key);
List<String> hVals(String key);
Set<Entry> hGetAll(String key);
Map<byte[], byte[]> hGetAll(byte[] key);
}

View File

@@ -25,29 +25,29 @@ import java.util.List;
*/
public interface RedisListCommands {
Integer rPush(String key, String value);
Integer rPush(byte[] key, byte[] value);
Integer lPush(String key, String value);
Integer lPush(byte[] key, byte[] value);
Integer lLen(String key);
Integer lLen(byte[] key);
List<String> lRange(String key, int start, int end);
List<byte[]> lRange(byte[] key, int start, int end);
void lTrim(String key, int start, int end);
void lTrim(byte[] key, int start, int end);
String lIndex(String key, int index);
byte[] lIndex(byte[] key, int index);
void lSet(String key, int index, String value);
void lSet(byte[] key, int index, byte[] value);
Integer lRem(String key, int count, String value);
Integer lRem(byte[] key, int count, byte[] value);
String lPop(String key);
byte[] lPop(byte[] key);
String rPop(String key);
byte[] rPop(byte[] key);
List<String> bLPop(int timeout, String... keys);
List<byte[]> bLPop(int timeout, byte[]... keys);
List<String> bRPop(int timeout, String... keys);
List<byte[]> bRPop(int timeout, byte[]... keys);
String rPopLPush(String srcKey, String dstKey);
byte[] rPopLPush(byte[] srcKey, byte[] dstKey);
}

View File

@@ -25,31 +25,31 @@ import java.util.Set;
*/
public interface RedisSetCommands {
Boolean sAdd(String key, String value);
Boolean sAdd(byte[] key, byte[] value);
Boolean sRem(String key, String value);
Boolean sRem(byte[] key, byte[] value);
String sPop(String key);
byte[] sPop(byte[] key);
Boolean sMove(String srcKey, String destKey, String value);
Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value);
Integer sCard(String key);
Integer sCard(byte[] key);
Boolean sIsMember(String key, String value);
Boolean sIsMember(byte[] key, byte[] value);
Set<String> sInter(String... keys);
Set<byte[]> sInter(byte[]... keys);
void sInterStore(String destKey, String... keys);
void sInterStore(byte[] destKey, byte[]... keys);
Set<String> sUnion(String... keys);
Set<byte[]> sUnion(byte[]... keys);
void sUnionStore(String destKey, String... keys);
void sUnionStore(byte[] destKey, byte[]... keys);
Set<String> sDiff(String... keys);
Set<byte[]> sDiff(byte[]... keys);
void sDiffStore(String destKey, String... keys);
void sDiffStore(byte[] destKey, byte[]... keys);
Set<String> sMembers(String key);
Set<byte[]> sMembers(byte[] key);
String sRandMember(String key);
byte[] sRandMember(byte[] key);
}

View File

@@ -17,6 +17,7 @@
package org.springframework.datastore.redis.connection;
import java.util.List;
import java.util.Map;
/**
* String specific commands supported by Redis.
@@ -25,31 +26,31 @@ import java.util.List;
*/
public interface RedisStringCommands {
void set(String key, String value);
void set(byte[] key, byte[] value);
String get(String key);
byte[] get(byte[] key);
String getSet(String key, String value);
byte[] getSet(byte[] key, byte[] value);
List<String> mGet(String... keys);
List<byte[]> mGet(byte[]... keys);
Boolean setNX(String key, String value);
Boolean setNX(byte[] key, byte[] value);
void setEx(String key, int seconds, String value);
void setEx(byte[] key, int seconds, byte[] value);
void mSet(String[] keys, String[] values);
void mSet(Map<byte[], byte[]> tuple);
void mSetNX(String[] keys, String[] values);
void mSetNX(Map<byte[], byte[]> tuple);
Integer incr(String key);
Integer incr(byte[] key);
Integer incrBy(String key, int value);
Integer incrBy(byte[] key, int value);
Integer decr(String key);
Integer decr(byte[] key);
Integer decrBy(String key, int value);
Integer decrBy(byte[] key, int value);
Integer append(String key, String value);
Integer append(byte[] key, byte[] value);
String substr(String key, int start, int end);
byte[] substr(byte[] key, int start, int end);
}

View File

@@ -31,7 +31,7 @@ public interface RedisTxCommands {
void discard();
void watch(String... keys);
void watch(byte[]... keys);
void unwatch();
}

View File

@@ -31,52 +31,52 @@ public interface RedisZSetCommands {
}
public interface Tuple {
String getValue();
byte[] getValue();
Double getScore();
}
Boolean zAdd(String key, double score, String value);
Boolean zAdd(byte[] key, double score, byte[] value);
Boolean zRem(String key, String value);
Boolean zRem(byte[] key, byte[] value);
Double zIncrBy(String key, double increment, String value);
Double zIncrBy(byte[] key, double increment, byte[] value);
Integer zRank(String key, String value);
Integer zRank(byte[] key, byte[] value);
Integer zRevRank(String key, String value);
Integer zRevRank(byte[] key, byte[] value);
Set<String> zRange(String key, int start, int end);
Set<byte[]> zRange(byte[] key, int start, int end);
Set<Tuple> zRangeWithScore(String key, int start, int end);
Set<Tuple> zRangeWithScore(byte[] key, int start, int end);
Set<String> zRevRange(String key, int start, int end);
Set<byte[]> zRevRange(byte[] key, int start, int end);
Set<Tuple> zRevRangeWithScore(String key, int start, int end);
Set<Tuple> zRevRangeWithScore(byte[] key, int start, int end);
Set<String> zRangeByScore(String key, double min, double max);
Set<byte[]> zRangeByScore(byte[] key, double min, double max);
Set<Tuple> zRangeByScoreWithScore(String key, double min, double max);
Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max);
Set<String> zRangeByScore(String key, double min, double max, int offset, int count);
Set<byte[]> zRangeByScore(byte[] key, double min, double max, int offset, int count);
Set<Tuple> zRangeByScoreWithScore(String key, double min, double max, int offset, int count);
Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max, int offset, int count);
Integer zCount(String key, double min, double max);
Integer zCount(byte[] key, double min, double max);
Integer zCard(String key);
Integer zCard(byte[] key);
Double zScore(String key, String value);
Double zScore(byte[] key, byte[] value);
Integer zRemRange(String key, int start, int end);
Integer zRemRange(byte[] key, int start, int end);
Integer zRemRangeByScore(String key, double min, double max);
Integer zRemRangeByScore(byte[] key, double min, double max);
Integer zUnionStore(String destKey, String... sets);
Integer zUnionStore(byte[] destKey, byte[]... sets);
Integer zUnionStore(String destKey, Aggregate aggregate, int[] weights, String... sets);
Integer zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets);
Integer zInterStore(String destKey, String... sets);
Integer zInterStore(byte[] destKey, byte[]... sets);
Integer zInterStore(String destKey, Aggregate aggregate, int[] weights, String... sets);
Integer zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets);
}

View File

@@ -17,8 +17,8 @@ package org.springframework.datastore.redis.connection.jedis;
import java.io.IOException;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -30,6 +30,8 @@ import org.springframework.datastore.redis.connection.DataType;
import org.springframework.datastore.redis.connection.RedisConnection;
import org.springframework.util.ReflectionUtils;
import redis.clients.jedis.BinaryJedis;
import redis.clients.jedis.BinaryTransaction;
import redis.clients.jedis.Client;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisException;
@@ -46,13 +48,13 @@ public class JedisConnection implements RedisConnection {
private static final Field CLIENT_FIELD;
static {
CLIENT_FIELD = ReflectionUtils.findField(Jedis.class, "client", Client.class);
CLIENT_FIELD = ReflectionUtils.findField(BinaryJedis.class, "client", Client.class);
ReflectionUtils.makeAccessible(CLIENT_FIELD);
}
private final Jedis jedis;
private final Client client;
private final Transaction transaction;
private final BinaryTransaction transaction;
public JedisConnection(Jedis jedis) {
this.jedis = jedis;
@@ -86,11 +88,6 @@ public class JedisConnection implements RedisConnection {
}
}
@Override
public String getEncoding() {
return "UTF-8";
}
@Override
public Jedis getNativeConnection() {
return jedis;
@@ -124,7 +121,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer del(String... keys) {
public Integer del(byte[]... keys) {
try {
if (isQueueing()) {
transaction.del(keys);
@@ -155,7 +152,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean exists(String key) {
public Boolean exists(byte[] key) {
try {
if (isQueueing()) {
transaction.exists(key);
@@ -168,7 +165,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean expire(String key, int seconds) {
public Boolean expire(byte[] key, int seconds) {
try {
if (isQueueing()) {
transaction.expire(key, seconds);
@@ -181,7 +178,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Collection<String> keys(String pattern) {
public Collection<byte[]> keys(byte[] pattern) {
try {
if (isQueueing()) {
transaction.keys(pattern);
@@ -203,7 +200,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean persist(String key) {
public Boolean persist(byte[] key) {
try {
if (isQueueing()) {
client.persist(key);
@@ -216,20 +213,20 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String randomKey() {
public byte[] randomKey() {
try {
if (isQueueing()) {
transaction.randomKey();
transaction.randomBinaryKey();
return null;
}
return jedis.randomKey();
return jedis.randomBinaryKey();
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public void rename(String oldName, String newName) {
public void rename(byte[] oldName, byte[] newName) {
try {
if (isQueueing()) {
transaction.rename(oldName, newName);
@@ -241,7 +238,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean renameNX(String oldName, String newName) {
public Boolean renameNX(byte[] oldName, byte[] newName) {
try {
if (isQueueing()) {
transaction.renamenx(oldName, newName);
@@ -266,7 +263,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer ttl(String key) {
public Integer ttl(byte[] key) {
try {
if (isQueueing()) {
transaction.ttl(key);
@@ -279,7 +276,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public DataType type(String key) {
public DataType type(byte[] key) {
try {
if (isQueueing()) {
transaction.type(key);
@@ -301,14 +298,14 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void watch(String... keys) {
public void watch(byte[]... keys) {
if (isQueueing()) {
// ignore (as watch not allowed in multi)
return;
}
try {
for (String key : keys) {
for (byte[] key : keys) {
jedis.watch(key);
}
} catch (Exception ex) {
@@ -321,7 +318,7 @@ public class JedisConnection implements RedisConnection {
//
@Override
public String get(String key) {
public byte[] get(byte[] key) {
try {
if (isQueueing()) {
transaction.get(key);
@@ -335,7 +332,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void set(String key, String value) {
public void set(byte[] key, byte[] value) {
try {
jedis.set(key, value);
} catch (Exception ex) {
@@ -345,7 +342,7 @@ public class JedisConnection implements RedisConnection {
@Override
public String getSet(String key, String value) {
public byte[] getSet(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.getSet(key, value);
@@ -358,7 +355,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer append(String key, String value) {
public Integer append(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.append(key, value);
@@ -371,7 +368,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public List<String> mGet(String... keys) {
public List<byte[]> mGet(byte[]... keys) {
try {
if (isQueueing()) {
transaction.mget(keys);
@@ -384,31 +381,31 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void mSet(String[] keys, String[] values) {
public void mSet(Map<byte[], byte[]> tuples) {
try {
if (isQueueing()) {
transaction.mset(JedisUtils.arrange(keys, values));
transaction.mset(JedisUtils.convert(tuples));
}
jedis.mset(JedisUtils.arrange(keys, values));
jedis.mset(JedisUtils.convert(tuples));
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public void mSetNX(String[] keys, String[] values) {
public void mSetNX(Map<byte[], byte[]> tuples) {
try {
if (isQueueing()) {
transaction.msetnx(JedisUtils.arrange(keys, values));
transaction.msetnx(JedisUtils.convert(tuples));
}
jedis.msetnx(JedisUtils.arrange(keys, values));
jedis.msetnx(JedisUtils.convert(tuples));
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public void setEx(String key, int time, String value) {
public void setEx(byte[] key, int time, byte[] value) {
try {
if (isQueueing()) {
transaction.setex(key, time, value);
@@ -420,7 +417,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean setNX(String key, String value) {
public Boolean setNX(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.setnx(key, value);
@@ -432,7 +429,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String substr(String key, int start, int end) {
public byte[] substr(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.substr(key, start, end);
@@ -445,7 +442,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer decr(String key) {
public Integer decr(byte[] key) {
try {
if (isQueueing()) {
transaction.decr(key);
@@ -458,7 +455,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer decrBy(String key, int value) {
public Integer decrBy(byte[] key, int value) {
try {
if (isQueueing()) {
transaction.decrBy(key, value);
@@ -471,7 +468,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer incr(String key) {
public Integer incr(byte[] key) {
try {
if (isQueueing()) {
transaction.incr(key);
@@ -484,7 +481,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer incrBy(String key, int value) {
public Integer incrBy(byte[] key, int value) {
try {
if (isQueueing()) {
transaction.incrBy(key, value);
@@ -502,7 +499,7 @@ public class JedisConnection implements RedisConnection {
@Override
public Integer lPush(String key, String value) {
public Integer lPush(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.lpush(key, value);
@@ -515,7 +512,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer rPush(String key, String value) {
public Integer rPush(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.rpush(key, value);
@@ -528,7 +525,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public List<String> bLPop(int timeout, String... keys) {
public List<byte[]> bLPop(int timeout, byte[]... keys) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -540,7 +537,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public List<String> bRPop(int timeout, String... keys) {
public List<byte[]> bRPop(int timeout, byte[]... keys) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -552,7 +549,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String lIndex(String key, int index) {
public byte[] lIndex(byte[] key, int index) {
try {
if (isQueueing()) {
transaction.lindex(key, index);
@@ -565,7 +562,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer lLen(String key) {
public Integer lLen(byte[] key) {
try {
if (isQueueing()) {
transaction.llen(key);
@@ -578,7 +575,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String lPop(String key) {
public byte[] lPop(byte[] key) {
try {
if (isQueueing()) {
transaction.lpop(key);
@@ -591,7 +588,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public List<String> lRange(String key, int start, int end) {
public List<byte[]> lRange(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.lrange(key, start, end);
@@ -604,7 +601,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer lRem(String key, int count, String value) {
public Integer lRem(byte[] key, int count, byte[] value) {
try {
if (isQueueing()) {
transaction.lrem(key, count, value);
@@ -617,7 +614,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void lSet(String key, int index, String value) {
public void lSet(byte[] key, int index, byte[] value) {
try {
if (isQueueing()) {
transaction.lset(key, index, value);
@@ -629,7 +626,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void lTrim(String key, int start, int end) {
public void lTrim(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.ltrim(key, start, end);
@@ -641,7 +638,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String rPop(String key) {
public byte[] rPop(byte[] key) {
try {
if (isQueueing()) {
transaction.rpop(key);
@@ -654,7 +651,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String rPopLPush(String srcKey, String dstKey) {
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
try {
if (isQueueing()) {
transaction.rpoplpush(srcKey, dstKey);
@@ -672,7 +669,7 @@ public class JedisConnection implements RedisConnection {
//
@Override
public Boolean sAdd(String key, String value) {
public Boolean sAdd(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.sadd(key, value);
@@ -685,7 +682,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer sCard(String key) {
public Integer sCard(byte[] key) {
try {
if (isQueueing()) {
transaction.scard(key);
@@ -698,7 +695,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> sDiff(String... keys) {
public Set<byte[]> sDiff(byte[]... keys) {
try {
if (isQueueing()) {
transaction.sdiff(keys);
@@ -711,7 +708,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void sDiffStore(String destKey, String... keys) {
public void sDiffStore(byte[] destKey, byte[]... keys) {
try {
if (isQueueing()) {
transaction.sdiffstore(destKey, keys);
@@ -723,7 +720,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> sInter(String... keys) {
public Set<byte[]> sInter(byte[]... keys) {
try {
if (isQueueing()) {
transaction.sinter(keys);
@@ -736,7 +733,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void sInterStore(String destKey, String... keys) {
public void sInterStore(byte[] destKey, byte[]... keys) {
try {
if (isQueueing()) {
transaction.sinterstore(destKey, keys);
@@ -748,7 +745,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean sIsMember(String key, String value) {
public Boolean sIsMember(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.sismember(key, value);
@@ -761,7 +758,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> sMembers(String key) {
public Set<byte[]> sMembers(byte[] key) {
try {
if (isQueueing()) {
transaction.smembers(key);
@@ -774,7 +771,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean sMove(String srcKey, String destKey, String value) {
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
try {
if (isQueueing()) {
transaction.smove(srcKey, destKey, value);
@@ -787,7 +784,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String sPop(String key) {
public byte[] sPop(byte[] key) {
try {
if (isQueueing()) {
transaction.spop(key);
@@ -800,7 +797,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String sRandMember(String key) {
public byte[] sRandMember(byte[] key) {
try {
if (isQueueing()) {
transaction.srandmember(key);
@@ -813,7 +810,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean sRem(String key, String value) {
public Boolean sRem(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.srem(key, value);
@@ -826,7 +823,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> sUnion(String... keys) {
public Set<byte[]> sUnion(byte[]... keys) {
try {
if (isQueueing()) {
transaction.sunion(keys);
@@ -839,7 +836,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void sUnionStore(String destKey, String... keys) {
public void sUnionStore(byte[] destKey, byte[]... keys) {
try {
if (isQueueing()) {
transaction.sunionstore(destKey, keys);
@@ -855,7 +852,7 @@ public class JedisConnection implements RedisConnection {
//
@Override
public Boolean zAdd(String key, double score, String value) {
public Boolean zAdd(byte[] key, double score, byte[] value) {
try {
if (isQueueing()) {
transaction.zadd(key, score, value);
@@ -868,7 +865,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zCard(String key) {
public Integer zCard(byte[] key) {
try {
if (isQueueing()) {
transaction.zcard(key);
@@ -881,7 +878,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zCount(String key, double min, double max) {
public Integer zCount(byte[] key, double min, double max) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -893,7 +890,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Double zIncrBy(String key, double increment, String value) {
public Double zIncrBy(byte[] key, double increment, byte[] value) {
try {
if (isQueueing()) {
transaction.zincrby(key, increment, value);
@@ -906,7 +903,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zInterStore(String destKey, Aggregate aggregate, int[] weights, String... sets) {
public Integer zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -920,7 +917,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zInterStore(String destKey, String... sets) {
public Integer zInterStore(byte[] destKey, byte[]... sets) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -932,7 +929,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> zRange(String key, int start, int end) {
public Set<byte[]> zRange(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.zrange(key, start, end);
@@ -945,7 +942,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<Tuple> zRangeWithScore(String key, int start, int end) {
public Set<Tuple> zRangeWithScore(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.zrangeWithScores(key, start, end);
@@ -958,7 +955,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> zRangeByScore(String key, double min, double max) {
public Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -970,7 +967,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<Tuple> zRangeByScoreWithScore(String key, double min, double max) {
public Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -982,7 +979,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<Tuple> zRevRangeWithScore(String key, int start, int end) {
public Set<Tuple> zRevRangeWithScore(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.zrangeWithScores(key, start, end);
@@ -995,7 +992,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> zRangeByScore(String key, double min, double max, int offset, int count) {
public Set<byte[]> zRangeByScore(byte[] key, double min, double max, int offset, int count) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1007,7 +1004,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<Tuple> zRangeByScoreWithScore(String key, double min, double max, int offset, int count) {
public Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max, int offset, int count) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1019,7 +1016,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zRank(String key, String value) {
public Integer zRank(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.zrank(key, value);
@@ -1032,7 +1029,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean zRem(String key, String value) {
public Boolean zRem(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.zrem(key, value);
@@ -1045,7 +1042,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zRemRange(String key, int start, int end) {
public Integer zRemRange(byte[] key, int start, int end) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1057,7 +1054,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zRemRangeByScore(String key, double min, double max) {
public Integer zRemRangeByScore(byte[] key, double min, double max) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1069,7 +1066,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> zRevRange(String key, int start, int end) {
public Set<byte[]> zRevRange(byte[] key, int start, int end) {
try {
if (isQueueing()) {
transaction.zrevrange(key, start, end);
@@ -1082,7 +1079,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zRevRank(String key, String value) {
public Integer zRevRank(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.zrevrank(key, value);
@@ -1095,7 +1092,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Double zScore(String key, String value) {
public Double zScore(byte[] key, byte[] value) {
try {
if (isQueueing()) {
transaction.zscore(key, value);
@@ -1108,7 +1105,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zUnionStore(String destKey, Aggregate aggregate, int[] weights, String... sets) {
public Integer zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1122,7 +1119,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Integer zUnionStore(String destKey, String... sets) {
public Integer zUnionStore(byte[] destKey, byte[]... sets) {
try {
if (isQueueing()) {
throw new UnsupportedOperationException();
@@ -1138,7 +1135,7 @@ public class JedisConnection implements RedisConnection {
//
@Override
public Boolean hSet(String key, String field, String value) {
public Boolean hSet(byte[] key, byte[] field, byte[] value) {
try {
if (isQueueing()) {
transaction.hset(key, field, value);
@@ -1151,7 +1148,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean hSetNX(String key, String field, String value) {
public Boolean hSetNX(byte[] key, byte[] field, byte[] value) {
try {
if (isQueueing()) {
transaction.hsetnx(key, field, value);
@@ -1164,7 +1161,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean hDel(String key, String field) {
public Boolean hDel(byte[] key, byte[] field) {
try {
if (isQueueing()) {
transaction.hdel(key, field);
@@ -1177,7 +1174,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Boolean hExists(String key, String field) {
public Boolean hExists(byte[] key, byte[] field) {
try {
if (isQueueing()) {
transaction.hexists(key, field);
@@ -1190,7 +1187,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public String hGet(String key, String field) {
public byte[] hGet(byte[] key, byte[] field) {
try {
if (isQueueing()) {
transaction.hget(key, field);
@@ -1203,20 +1200,20 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<Entry> hGetAll(String key) {
public Map<byte[], byte[]> hGetAll(byte[] key) {
try {
if (isQueueing()) {
transaction.hgetAll(key);
return null;
}
return JedisUtils.convert(jedis.hgetAll(key));
return jedis.hgetAll(key);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public Integer hIncrBy(String key, String field, int delta) {
public Integer hIncrBy(byte[] key, byte[] field, int delta) {
try {
if (isQueueing()) {
transaction.hincrBy(key, field, delta);
@@ -1229,20 +1226,20 @@ public class JedisConnection implements RedisConnection {
}
@Override
public Set<String> hKeys(String key) {
public Set<byte[]> hKeys(byte[] key) {
try {
if (isQueueing()) {
transaction.hkeys(key);
return null;
}
return new LinkedHashSet<String>(jedis.hkeys(key));
return jedis.hkeys(key);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public Integer hLen(String key) {
public Integer hLen(byte[] key) {
try {
if (isQueueing()) {
transaction.hlen(key);
@@ -1255,7 +1252,7 @@ public class JedisConnection implements RedisConnection {
}
@Override
public List<String> hMGet(String key, String... fields) {
public List<byte[]> hMGet(byte[] key, byte[]... fields) {
try {
if (isQueueing()) {
transaction.hmget(key, fields);
@@ -1268,26 +1265,25 @@ public class JedisConnection implements RedisConnection {
}
@Override
public void hMSet(String key, String[] fields, String[] values) {
Map<String, String> param = JedisUtils.convert(fields, values);
public void hMSet(byte[] key, Map<byte[], byte[]> tuple) {
try {
if (isQueueing()) {
transaction.hmset(key, param);
transaction.hmset(key, tuple);
}
jedis.hmset(key, param);
jedis.hmset(key, tuple);
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}
}
@Override
public List<String> hVals(String key) {
public List<byte[]> hVals(byte[] key) {
try {
if (isQueueing()) {
transaction.hvals(key);
return null;
}
return jedis.hvals(key);
return new ArrayList<byte[]>(jedis.hvals(key));
} catch (Exception ex) {
throw convertJedisAccessException(ex);
}

View File

@@ -117,10 +117,11 @@ public class JedisConnectionFactory implements InitializingBean, DisposableBean,
int size = getPoolSize();
pool = new JedisPool(shardInfo);
pool.setResourcesNumber(size);
pool.init();
}
}
public void destroy() throws Exception {
public void destroy() {
if (usePool && pool != null) {
pool.destroy();
pool = null;

View File

@@ -28,9 +28,7 @@ import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.datastore.redis.RedisConnectionFailureException;
import org.springframework.datastore.redis.UncategorizedRedisException;
import org.springframework.datastore.redis.connection.DefaultEntry;
import org.springframework.datastore.redis.connection.DefaultTuple;
import org.springframework.datastore.redis.connection.RedisHashCommands.Entry;
import org.springframework.datastore.redis.connection.RedisZSetCommands.Tuple;
import redis.clients.jedis.JedisException;
@@ -79,19 +77,21 @@ public abstract class JedisUtils {
static Set<Tuple> convertJedisTuple(Set<redis.clients.jedis.Tuple> tuples) {
Set<Tuple> value = new LinkedHashSet<Tuple>(tuples.size());
for (redis.clients.jedis.Tuple tuple : tuples) {
value.add(new DefaultTuple(tuple.getElement(), tuple.getScore()));
value.add(new DefaultTuple(tuple.getBinaryElement(), tuple.getScore()));
}
return value;
}
static Set<Entry> convert(Map<String, String> hgetAll) {
Set<Entry> entries = new LinkedHashSet<Entry>(hgetAll.size());
for (Map.Entry<String, String> entry : hgetAll.entrySet()) {
entries.add(new DefaultEntry(entry.getKey(), entry.getValue()));
}
static byte[][] convert(Map<byte[], byte[]> hgetAll) {
byte[][] result = new byte[hgetAll.size() * 2][];
return entries;
int index = 0;
for (Map.Entry<byte[], byte[]> entry : hgetAll.entrySet()) {
result[index++] = entry.getKey();
result[index++] = entry.getValue();
}
return result;
}
static Map<String, String> convert(String[] fields, String[] values) {

View File

@@ -15,10 +15,12 @@
*/
package org.springframework.datastore.redis.connection.jredis;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jredis.JRedis;
@@ -30,16 +32,19 @@ import org.springframework.datastore.redis.connection.DataType;
import org.springframework.datastore.redis.connection.RedisConnection;
/**
* JRedis based implementation.
*
* @author Costin Leau
*/
public class JredisConnection implements RedisConnection {
private final JRedis jredis;
private final String encoding;
public JredisConnection(JRedis jredis, String encoding) {
private final Charset charset;
public JredisConnection(JRedis jredis, Charset charset) {
this.jredis = jredis;
this.encoding = encoding;
this.charset = charset;
}
protected DataAccessException convertJedisAccessException(Exception ex) {
@@ -55,11 +60,6 @@ public class JredisConnection implements RedisConnection {
}
@Override
public String getEncoding() {
return encoding;
}
@Override
public JRedis getNativeConnection() {
return jredis;
@@ -85,9 +85,9 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Integer del(String... keys) {
public Integer del(byte[]... keys) {
try {
return Integer.valueOf((int) jredis.del(keys));
return Integer.valueOf((int) jredis.del(JredisUtils.convertMultiple(charset, keys)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -108,27 +108,27 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Boolean exists(String key) {
public Boolean exists(byte[] key) {
try {
return jredis.exists(key);
return jredis.exists(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean expire(String key, int seconds) {
public Boolean expire(byte[] key, int seconds) {
try {
return jredis.expire(key, seconds);
return jredis.expire(JredisUtils.convert(charset, key), seconds);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Collection<String> keys(String pattern) {
public Collection<byte[]> keys(byte[] pattern) {
try {
return jredis.keys(pattern);
return JredisUtils.convert(charset, jredis.keys(JredisUtils.convert(charset, pattern)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -140,32 +140,32 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Boolean persist(String key) {
public Boolean persist(byte[] key) {
throw new UnsupportedOperationException();
}
@Override
public String randomKey() {
public byte[] randomKey() {
try {
return jredis.randomkey();
return JredisUtils.convert(charset, jredis.randomkey());
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void rename(String oldName, String newName) {
public void rename(byte[] oldName, byte[] newName) {
try {
jredis.rename(oldName, newName);
jredis.rename(JredisUtils.convert(charset, oldName), JredisUtils.convert(charset, newName));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean renameNX(String oldName, String newName) {
public Boolean renameNX(byte[] oldName, byte[] newName) {
try {
return jredis.renamenx(oldName, newName);
return jredis.renamenx(JredisUtils.convert(charset, oldName), JredisUtils.convert(charset, newName));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -177,18 +177,18 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Integer ttl(String key) {
public Integer ttl(byte[] key) {
try {
return Integer.valueOf((int) jredis.ttl(key));
return Integer.valueOf((int) jredis.ttl(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public DataType type(String key) {
public DataType type(byte[] key) {
try {
return JredisUtils.convertDataType(jredis.type(key));
return JredisUtils.convertDataType(jredis.type(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -200,7 +200,7 @@ public class JredisConnection implements RedisConnection {
}
@Override
public void watch(String... keys) {
public void watch(byte[]... keys) {
throw new UnsupportedOperationException();
}
@@ -209,123 +209,122 @@ public class JredisConnection implements RedisConnection {
//
@Override
public String get(String key) {
public byte[] get(byte[] key) {
try {
return JredisUtils.convertToString(jredis.get(key), encoding);
return jredis.get(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void set(String key, String value) {
public void set(byte[] key, byte[] value) {
try {
jredis.set(key, value);
jredis.set(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String getSet(String key, String value) {
public byte[] getSet(byte[] key, byte[] value) {
try {
return JredisUtils.convertToString(jredis.getset(key, value), encoding);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer append(String key, String value) {
try {
return Integer.valueOf((int) jredis.append(key, value));
return jredis.getset(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public List<String> mGet(String... keys) {
public Integer append(byte[] key, byte[] value) {
try {
return JredisUtils.convertToStringCollection(jredis.mget(keys), encoding, List.class);
return Integer.valueOf((int) jredis.append(JredisUtils.convert(charset, key), value));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void mSet(String[] keys, String[] values) {
public List<byte[]> mGet(byte[]... keys) {
try {
jredis.mset(JredisUtils.convert(keys, values));
return jredis.mget(JredisUtils.convertMultiple(charset, keys));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void mSetNX(String[] keys, String[] values) {
public void mSet(Map<byte[], byte[]> tuple) {
try {
jredis.msetnx(JredisUtils.convert(keys, values));
jredis.mset(JredisUtils.convert(charset, tuple));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void setEx(String key, int seconds, String value) {
public void mSetNX(Map<byte[], byte[]> tuple) {
try {
jredis.msetnx(JredisUtils.convert(charset, tuple));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void setEx(byte[] key, int seconds, byte[] value) {
throw new UnsupportedOperationException();
}
@Override
public Boolean setNX(String key, String value) {
public Boolean setNX(byte[] key, byte[] value) {
try {
return jredis.setnx(key, value);
return jredis.setnx(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String substr(String key, int start, int end) {
public byte[] substr(byte[] key, int start, int end) {
try {
return JredisUtils.convertToString(jredis.substr(key, (long) start, (long) end), encoding);
return jredis.substr(JredisUtils.convert(charset, key), (long) start, (long) end);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer decr(String key) {
public Integer decr(byte[] key) {
try {
return (int) jredis.decr(key);
return (int) jredis.decr(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer decrBy(String key, int value) {
public Integer decrBy(byte[] key, int value) {
try {
return (int) jredis.decrby(key, value);
return (int) jredis.decrby(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer incr(String key) {
public Integer incr(byte[] key) {
try {
return (int) jredis.incr(key);
return (int) jredis.incr(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer incrBy(String key, int value) {
public Integer incrBy(byte[] key, int value) {
try {
return (int) jredis.incrby(key, value);
return (int) jredis.incrby(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -336,46 +335,46 @@ public class JredisConnection implements RedisConnection {
//
@Override
public List<String> bLPop(int timeout, String... keys) {
public List<byte[]> bLPop(int timeout, byte[]... keys) {
throw new UnsupportedOperationException();
}
@Override
public List<String> bRPop(int timeout, String... keys) {
public List<byte[]> bRPop(int timeout, byte[]... keys) {
throw new UnsupportedOperationException();
}
@Override
public String lIndex(String key, int index) {
public byte[] lIndex(byte[] key, int index) {
try {
return JredisUtils.convertToString(jredis.lindex(key, (long) index), encoding);
return jredis.lindex(JredisUtils.convert(charset, key), (long) index);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer lLen(String key) {
public Integer lLen(byte[] key) {
try {
return Integer.valueOf((int) jredis.llen(key));
return Integer.valueOf((int) jredis.llen(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String lPop(String key) {
public byte[] lPop(byte[] key) {
try {
return JredisUtils.convertToString(jredis.lpop(key), encoding);
return jredis.lpop(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer lPush(String key, String value) {
public Integer lPush(byte[] key, byte[] value) {
try {
jredis.lpush(key, value);
jredis.lpush(JredisUtils.convert(charset, key), value);
return null;
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
@@ -383,66 +382,65 @@ public class JredisConnection implements RedisConnection {
}
@Override
public List<String> lRange(String key, int start, int end) {
public List<byte[]> lRange(byte[] key, int start, int end) {
try {
List<byte[]> lrange = jredis.lrange(key, start, end);
List<byte[]> lrange = jredis.lrange(JredisUtils.convert(charset, key), start, end);
return JredisUtils.convertToStringCollection(lrange, encoding, List.class);
return lrange;
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer lRem(String key, int count, String value) {
public Integer lRem(byte[] key, int count, byte[] value) {
try {
Integer.valueOf((int) jredis.lrem(key, value, count));
return null;
return Integer.valueOf((int) jredis.lrem(JredisUtils.convert(charset, key), value, count));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void lSet(String key, int index, String value) {
public void lSet(byte[] key, int index, byte[] value) {
try {
jredis.lset(key, index, value);
jredis.lset(JredisUtils.convert(charset, key), index, value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void lTrim(String key, int start, int end) {
public void lTrim(byte[] key, int start, int end) {
try {
jredis.ltrim(key, start, end);
jredis.ltrim(JredisUtils.convert(charset, key), start, end);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String rPop(String key) {
public byte[] rPop(byte[] key) {
try {
return JredisUtils.convertToString(jredis.rpop(key), encoding);
return jredis.rpop(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String rPopLPush(String srcKey, String dstKey) {
public byte[] rPopLPush(byte[] srcKey, byte[] dstKey) {
try {
return JredisUtils.convertToString(jredis.rpoplpush(srcKey, dstKey), encoding);
return jredis.rpoplpush(JredisUtils.convert(charset, srcKey), JredisUtils.convert(charset, dstKey));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer rPush(String key, String value) {
public Integer rPush(byte[] key, byte[] value) {
try {
jredis.rpush(key, value);
jredis.rpush(JredisUtils.convert(charset, key), value);
return null;
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
@@ -454,40 +452,40 @@ public class JredisConnection implements RedisConnection {
//
@Override
public Boolean sAdd(String key, String value) {
public Boolean sAdd(byte[] key, byte[] value) {
try {
return jredis.sadd(key, value);
return jredis.sadd(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer sCard(String key) {
public Integer sCard(byte[] key) {
try {
return Integer.valueOf((int) jredis.scard(key));
return Integer.valueOf((int) jredis.scard(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<String> sDiff(String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public Set<byte[]> sDiff(byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
List<byte[]> result = jredis.sdiff(set1, sets);
return JredisUtils.convertToStringCollection(result, encoding, Set.class);
return new LinkedHashSet<byte[]>(result);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void sDiffStore(String destKey, String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public void sDiffStore(byte[] destKey, byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
jredis.sdiffstore(set1, sets);
@@ -497,22 +495,22 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Set<String> sInter(String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public Set<byte[]> sInter(byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
List<byte[]> result = jredis.sinter(set1, sets);
return JredisUtils.convertToStringCollection(result, encoding, Set.class);
return new LinkedHashSet<byte[]>(result);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void sInterStore(String destKey, String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public void sInterStore(byte[] destKey, byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
jredis.sinterstore(set1, sets);
@@ -522,76 +520,75 @@ public class JredisConnection implements RedisConnection {
}
@Override
public Boolean sIsMember(String key, String value) {
public Boolean sIsMember(byte[] key, byte[] value) {
try {
return jredis.sismember(key, value);
return jredis.sismember(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<String> sMembers(String key) {
public Set<byte[]> sMembers(byte[] key) {
try {
return JredisUtils.convertToStringCollection(jredis.smembers(key), encoding, Set.class);
return new LinkedHashSet<byte[]>(jredis.smembers(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean sMove(String srcKey, String destKey, String value) {
public Boolean sMove(byte[] srcKey, byte[] destKey, byte[] value) {
try {
return jredis.smove(srcKey, destKey, value);
return jredis.smove(JredisUtils.convert(charset, srcKey), JredisUtils.convert(charset, destKey), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String sPop(String key) {
public byte[] sPop(byte[] key) {
try {
return JredisUtils.convertToString(jredis.spop(key), encoding);
return jredis.spop(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String sRandMember(String key) {
public byte[] sRandMember(byte[] key) {
try {
return JredisUtils.convertToString(jredis.srandmember(key), encoding);
return jredis.srandmember(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean sRem(String key, String value) {
public Boolean sRem(byte[] key, byte[] value) {
try {
return jredis.srem(key, value);
return jredis.srem(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<String> sUnion(String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public Set<byte[]> sUnion(byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
List<byte[]> result = jredis.sunion(set1, sets);
return JredisUtils.convertToStringCollection(result, encoding, Set.class);
return new LinkedHashSet<byte[]>(jredis.sunion(set1, sets));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public void sUnionStore(String destKey, String... keys) {
String set1 = keys[0];
String[] sets = Arrays.copyOfRange(keys, 1, keys.length);
public void sUnionStore(byte[] destKey, byte[]... keys) {
String set1 = JredisUtils.convert(charset, keys[0]);
String[] sets = JredisUtils.convertMultiple(charset, Arrays.copyOfRange(keys, 1, keys.length));
try {
jredis.sunionstore(set1, sets);
@@ -606,154 +603,153 @@ public class JredisConnection implements RedisConnection {
//
@Override
public Boolean zAdd(String key, double score, String value) {
public Boolean zAdd(byte[] key, double score, byte[] value) {
try {
return jredis.zadd(key, score, value);
return jredis.zadd(JredisUtils.convert(charset, key), score, value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer zCard(String key) {
public Integer zCard(byte[] key) {
try {
return Integer.valueOf((int) jredis.zcard(key));
return Integer.valueOf((int) jredis.zcard(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer zCount(String key, double min, double max) {
public Integer zCount(byte[] key, double min, double max) {
try {
return Integer.valueOf((int) jredis.zcount(key, min, max));
return Integer.valueOf((int) jredis.zcount(JredisUtils.convert(charset, key), min, max));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Double zIncrBy(String key, double increment, String value) {
public Double zIncrBy(byte[] key, double increment, byte[] value) {
try {
return jredis.zincrby(key, increment, value);
return jredis.zincrby(JredisUtils.convert(charset, key), increment, value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer zInterStore(String destKey, Aggregate aggregate, int[] weights, String... sets) {
public Integer zInterStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
throw new UnsupportedOperationException();
}
@Override
public Integer zInterStore(String destKey, String... sets) {
public Integer zInterStore(byte[] destKey, byte[]... sets) {
throw new UnsupportedOperationException();
}
@Override
public Set<String> zRange(String key, int start, int end) {
public Set<byte[]> zRange(byte[] key, int start, int end) {
try {
return JredisUtils.convertToStringCollection(jredis.zrange(key, (long) start, (long) end), encoding,
Set.class);
return new LinkedHashSet<byte[]>(jredis.zrange(JredisUtils.convert(charset, key), (long) start, (long) end));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<Tuple> zRangeWithScore(String key, int start, int end) {
public Set<Tuple> zRangeWithScore(byte[] key, int start, int end) {
throw new UnsupportedOperationException();
}
@Override
public Set<String> zRangeByScore(String key, double min, double max) {
public Set<byte[]> zRangeByScore(byte[] key, double min, double max) {
try {
return JredisUtils.convertToStringCollection(jredis.zrangebyscore(key, min, max), encoding, Set.class);
return new LinkedHashSet<byte[]>(jredis.zrangebyscore(JredisUtils.convert(charset, key), min, max));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<Tuple> zRangeByScoreWithScore(String key, double min, double max) {
public Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max) {
throw new UnsupportedOperationException();
}
@Override
public Set<String> zRangeByScore(String key, double min, double max, int offset, int count) {
public Set<byte[]> zRangeByScore(byte[] key, double min, double max, int offset, int count) {
throw new UnsupportedOperationException();
}
@Override
public Set<Tuple> zRangeByScoreWithScore(String key, double min, double max, int offset, int count) {
public Set<Tuple> zRangeByScoreWithScore(byte[] key, double min, double max, int offset, int count) {
throw new UnsupportedOperationException();
}
@Override
public Integer zRank(String key, String value) {
public Integer zRank(byte[] key, byte[] value) {
try {
return Integer.valueOf((int) jredis.zrank(key, value));
return Integer.valueOf((int) jredis.zrank(JredisUtils.convert(charset, key), value));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean zRem(String key, String value) {
public Boolean zRem(byte[] key, byte[] value) {
try {
return jredis.zrem(key, value);
return jredis.zrem(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer zRemRange(String key, int start, int end) {
public Integer zRemRange(byte[] key, int start, int end) {
try {
return Integer.valueOf((int) jredis.zremrangebyrank(key, start, end));
return Integer.valueOf((int) jredis.zremrangebyrank(JredisUtils.convert(charset, key), start, end));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer zRemRangeByScore(String key, double min, double max) {
public Integer zRemRangeByScore(byte[] key, double min, double max) {
try {
return Integer.valueOf((int) jredis.zremrangebyscore(key, min, max));
return Integer.valueOf((int) jredis.zremrangebyscore(JredisUtils.convert(charset, key), min, max));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<String> zRevRange(String key, int start, int end) {
public Set<byte[]> zRevRange(byte[] key, int start, int end) {
try {
return JredisUtils.convertToStringCollection(jredis.zrevrange(key, start, end), encoding, Set.class);
return new LinkedHashSet<byte[]>(jredis.zrevrange(JredisUtils.convert(charset, key), start, end));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<Tuple> zRevRangeWithScore(String key, int start, int end) {
public Set<Tuple> zRevRangeWithScore(byte[] key, int start, int end) {
throw new UnsupportedOperationException();
}
@Override
public Integer zRevRank(String key, String value) {
public Integer zRevRank(byte[] key, byte[] value) {
try {
return Integer.valueOf((int) jredis.zrevrank(key, value));
return Integer.valueOf((int) jredis.zrevrank(JredisUtils.convert(charset, key), value));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Double zScore(String key, String value) {
public Double zScore(byte[] key, byte[] value) {
try {
return jredis.zscore(key, value);
return jredis.zscore(JredisUtils.convert(charset, key), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
@@ -765,102 +761,103 @@ public class JredisConnection implements RedisConnection {
//
@Override
public Integer zUnionStore(String destKey, Aggregate aggregate, int[] weights, String... sets) {
public Integer zUnionStore(byte[] destKey, Aggregate aggregate, int[] weights, byte[]... sets) {
throw new UnsupportedOperationException();
}
@Override
public Integer zUnionStore(String destKey, String... sets) {
public Integer zUnionStore(byte[] destKey, byte[]... sets) {
throw new UnsupportedOperationException();
}
@Override
public Boolean hDel(String key, String field) {
public Boolean hDel(byte[] key, byte[] field) {
try {
return jredis.hdel(key, field);
return jredis.hdel(JredisUtils.convert(charset, key), JredisUtils.convert(charset, field));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean hExists(String key, String field) {
public Boolean hExists(byte[] key, byte[] field) {
try {
return jredis.hexists(key, field);
return jredis.hexists(JredisUtils.convert(charset, key), JredisUtils.convert(charset, field));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public String hGet(String key, String field) {
public byte[] hGet(byte[] key, byte[] field) {
try {
return JredisUtils.convertToString(jredis.hget(key, field), encoding);
return jredis.hget(JredisUtils.convert(charset, key), JredisUtils.convert(charset, field));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Set<Entry> hGetAll(String key) {
public Map<byte[], byte[]> hGetAll(byte[] key) {
try {
return JredisUtils.convert(jredis.hgetall(key), encoding);
return JredisUtils.convertMap(charset, jredis.hgetall(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer hIncrBy(String key, String field, int delta) {
public Integer hIncrBy(byte[] key, byte[] field, int delta) {
throw new UnsupportedOperationException();
}
@Override
public Set<String> hKeys(String key) {
public Set<byte[]> hKeys(byte[] key) {
try {
return new LinkedHashSet<String>(jredis.hkeys(key));
return new LinkedHashSet<byte[]>(JredisUtils.convert(charset,
jredis.hkeys(JredisUtils.convert(charset, key))));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Integer hLen(String key) {
public Integer hLen(byte[] key) {
try {
return Integer.valueOf((int) jredis.hlen(key));
return Integer.valueOf((int) jredis.hlen(JredisUtils.convert(charset, key)));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public List<String> hMGet(String key, String... fields) {
public List<byte[]> hMGet(byte[] key, byte[]... fields) {
throw new UnsupportedOperationException();
}
@Override
public void hMSet(String key, String[] fields, String[] values) {
public void hMSet(byte[] key, Map<byte[], byte[]> values) {
throw new UnsupportedOperationException();
}
@Override
public Boolean hSet(String key, String field, String value) {
public Boolean hSet(byte[] key, byte[] field, byte[] value) {
try {
return jredis.hset(key, field, value);
return jredis.hset(JredisUtils.convert(charset, key), JredisUtils.convert(charset, field), value);
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}
}
@Override
public Boolean hSetNX(String key, String field, String value) {
public Boolean hSetNX(byte[] key, byte[] field, byte[] value) {
throw new UnsupportedOperationException();
}
@Override
public List<String> hVals(String key) {
public List<byte[]> hVals(byte[] key) {
try {
return JredisUtils.convertToStringCollection(jredis.hvals(key), encoding, List.class);
return jredis.hvals(JredisUtils.convert(charset, key));
} catch (RedisException ex) {
throw JredisUtils.convertJredisAccessException(ex);
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.datastore.redis.connection.jredis;
import java.nio.charset.Charset;
import org.jredis.JRedis;
import org.jredis.connector.ConnectionSpec;
import org.jredis.connector.Connection.Socket.Property;
@@ -36,7 +38,6 @@ import org.springframework.util.StringUtils;
*/
public class JredisConnectionFactory implements InitializingBean, DisposableBean, RedisConnectionFactory {
private String encoding = "UTF-8";
private ConnectionSpec connectionSpec;
private String password;
@@ -49,6 +50,9 @@ public class JredisConnectionFactory implements InitializingBean, DisposableBean
private int poolSize = 5;
private Charset charset = Charset.forName("UTF8");
/**
* Constructs a new <code>JredisConnectionFactory</code> instance.
*/
@@ -88,7 +92,6 @@ public class JredisConnectionFactory implements InitializingBean, DisposableBean
this.connectionSpec = connectionSpec;
}
@Override
public void afterPropertiesSet() {
if (StringUtils.hasLength(password)) {
@@ -117,7 +120,7 @@ public class JredisConnectionFactory implements InitializingBean, DisposableBean
@Override
public RedisConnection getConnection() {
return new JredisConnection((usePool ? pool : new JRedisClient(connectionSpec)), getEncoding());
return new JredisConnection((usePool ? pool : new JRedisClient(connectionSpec)), charset);
}
@@ -126,22 +129,6 @@ public class JredisConnectionFactory implements InitializingBean, DisposableBean
return null;
}
/**
* Returns the encoding.
*
* @return Returns the encoding
*/
public String getEncoding() {
return encoding;
}
/**
* @param encoding The encoding to set.
*/
public void setEncoding(String encoding) {
this.encoding = encoding;
}
/**
* @return the password
*/
@@ -191,4 +178,21 @@ public class JredisConnectionFactory implements InitializingBean, DisposableBean
this.poolSize = poolSize;
usePool = true;
}
/**
*
* @return
*/
public Charset getCharset() {
return charset;
}
/**
* @param charset
*/
public void setCharset(Charset charset) {
this.charset = charset;
}
}

View File

@@ -16,23 +16,18 @@
package org.springframework.datastore.redis.connection.jredis;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import org.jredis.RedisException;
import org.jredis.RedisType;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.DataRetrievalFailureException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.datastore.redis.connection.DataType;
import org.springframework.datastore.redis.connection.DefaultEntry;
import org.springframework.datastore.redis.connection.RedisHashCommands.Entry;
/**
* Helper class featuring methods for JRedis connection handling, providing support for exception translation.
@@ -45,27 +40,16 @@ public abstract class JredisUtils {
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
}
static String convertToString(byte[] bytes, String encoding) {
try {
return new String(bytes, encoding);
} catch (UnsupportedEncodingException ex) {
throw new DataRetrievalFailureException("Unsupported encoding " + encoding, ex);
}
static String convert(Charset charset, byte[] bytes) {
return new String(bytes, charset);
}
static <T extends Collection<String>> T convertToStringCollection(List<byte[]> bytes, String encoding, Class<T> collectionType) {
Collection<String> col = (List.class.isAssignableFrom(collectionType) ? new ArrayList<String>(bytes.size())
: new LinkedHashSet<String>(bytes.size()));
try {
for (byte[] bs : bytes) {
col.add(new String(bs, encoding));
}
return (T) col;
} catch (UnsupportedEncodingException ex) {
throw new DataRetrievalFailureException("Unsupported encoding " + encoding, ex);
static String[] convertMultiple(Charset charset, byte[]... bytes) {
String[] result = new String[bytes.length];
for (int i = 0; i < bytes.length; i++) {
result[i] = new String(bytes[i], charset);
}
return result;
}
static DataType convertDataType(RedisType type) {
@@ -87,23 +71,31 @@ public abstract class JredisUtils {
return null;
}
static Set<Entry> convert(Map<String, byte[]> map, String encoding) {
Set<Entry> entries = new LinkedHashSet<Entry>(map.size());
try {
for (Map.Entry<String, byte[]> entry : map.entrySet()) {
entries.add(new DefaultEntry(entry.getKey(), new String(entry.getValue(), encoding)));
}
} catch (UnsupportedEncodingException ex) {
throw new DataRetrievalFailureException("Unsupported encoding " + encoding, ex);
static Map<byte[], byte[]> convertMap(Charset charset, Map<String, byte[]> map) {
Map<byte[], byte[]> result = new LinkedHashMap<byte[], byte[]>(map.size());
for (Map.Entry<String, byte[]> entry : map.entrySet()) {
result.put(entry.getKey().getBytes(charset), entry.getValue());
}
return entries;
return result;
}
static Map<String, byte[]> convert(String[] keys, String[] values) {
Map<String, byte[]> result = new LinkedHashMap<String, byte[]>(keys.length);
static Collection<byte[]> convert(Charset charset, List<String> keys) {
Collection<byte[]> list = new ArrayList<byte[]>(keys.size());
for (int i = 0; i < values.length; i++) {
result.put(keys[i], values[i].getBytes());
for (String string : keys) {
list.add(string.getBytes(charset));
}
return list;
}
static byte[] convert(Charset charset, String string) {
return string.getBytes(charset);
}
static Map<String, byte[]> convert(Charset charset, Map<byte[], byte[]> tuple) {
Map<String, byte[]> result = new LinkedHashMap<String, byte[]>(tuple.size());
for (Map.Entry<byte[], byte[]> entry : tuple.entrySet()) {
result.put(new String(entry.getKey(), charset), entry.getValue());
}
return result;
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.List;
/**
* List operations bound to a certain key.
*
* @author Costin Leau
*/
public interface BoundListOperations<K, V> extends KeyBound<K> {
List<V> range(int start, int end);
void trim(int start, int end);
Integer length();
Integer leftPush(V value);
Integer rightPush(V value);
V leftPop();
V rightPop();
Integer remove(int i, Object value);
V index(int index);
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* Set operations bound to a certain key.
*
* @author Costin Leau
*/
public interface BoundSetOperations<K, V> extends KeyBound<K> {
Set<V> diff(K... keys);
void diffAndStore(K destKey, K... keys);
RedisOperations<K, V> getOperations();
Set<V> intersect(K... keys);
void intersectAndStore(K destKey, K... keys);
Set<V> union(K... keys);
void unionAndStore(K destKey, K... keys);
Boolean add(V value);
boolean isMember(Object o);
Set<V> members();
boolean remove(Object o);
int size();
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* ZSet (or SortedSet) operations bound to a certain key.
*
* @author Costin Leau
*/
public interface BoundZSetOperations<K, V> extends KeyBound<K> {
RedisOperations<K, V> getOperations();
void intersectAndStore(K destKey, K... keys);
Set<V> range(int start, int end);
Set<V> rangeByScore(double min, double max);
void removeRange(int start, int end);
void removeRangeByScore(double min, double max);
void unionAndStore(K destKey, K... keys);
boolean add(V value, double score);
Integer rank(Object o);
boolean remove(Object o);
int size();
Set<V> reverseRange(int start, int end);
}

View File

@@ -0,0 +1,79 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.List;
/**
* Default implementation for {@link BoundListOperations}.
*
* @author Costin Leau
*/
public class DefaultBoundListOperations<K, V> extends DefaultKeyBound<K> implements BoundListOperations<K, V> {
private final ListOperations<K, V> ops;
public DefaultBoundListOperations(K key, RedisTemplate<K, V> template) {
super(key);
this.ops = template.listOps();
}
@Override
public V index(int index) {
throw new UnsupportedOperationException();
}
@Override
public V leftPop() {
throw new UnsupportedOperationException();
}
@Override
public Integer leftPush(V value) {
throw new UnsupportedOperationException();
}
@Override
public Integer length() {
throw new UnsupportedOperationException();
}
@Override
public List<V> range(int start, int end) {
throw new UnsupportedOperationException();
}
@Override
public Integer remove(int i, Object value) {
throw new UnsupportedOperationException();
}
@Override
public V rightPop() {
throw new UnsupportedOperationException();
}
@Override
public Integer rightPush(V value) {
throw new UnsupportedOperationException();
}
@Override
public void trim(int start, int end) {
throw new UnsupportedOperationException();
}
}

View File

@@ -0,0 +1,95 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* Default implementation for {@link BoundSetOperations}.
*
* @author Costin Leau
*/
class DefaultBoundSetOperations<K, V> extends DefaultKeyBound<K> implements BoundSetOperations<K, V> {
private final SetOperations<K, V> ops;
DefaultBoundSetOperations(K key, RedisTemplate<K, V> template) {
super(key);
this.ops = template.setOps();
}
@Override
public Boolean add(V value) {
return ops.add(getKey(), value);
}
@Override
public Set<V> diff(K... keys) {
return ops.diff(getKey(), keys);
}
@Override
public void diffAndStore(K destKey, K... keys) {
ops.diffAndStore(getKey(), destKey, keys);
}
@Override
public RedisOperations<K, V> getOperations() {
return ops.getOperations();
}
@Override
public Set<V> intersect(K... keys) {
return ops.intersect(getKey(), keys);
}
@Override
public void intersectAndStore(K destKey, K... keys) {
ops.intersectAndStore(getKey(), destKey, keys);
}
@Override
public boolean isMember(Object o) {
return ops.isMember(getKey(), o);
}
@Override
public Set<V> members() {
return ops.members(getKey());
}
@Override
public boolean remove(Object o) {
return ops.remove(getKey(), o);
}
@Override
public int size() {
return ops.size(getKey());
}
@Override
public Set<V> union(K... keys) {
return ops.union(getKey(), keys);
}
@Override
public void unionAndStore(K destKey, K... keys) {
ops.unionAndStore(getKey(), destKey, keys);
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* Default implementation for {@link BoundZSetOperations}.
*
* @author Costin Leau
*/
class DefaultBoundZSetOperations<K, V> extends DefaultKeyBound<K> implements BoundZSetOperations<K, V> {
private final ZSetOperations<K, V> ops;
public DefaultBoundZSetOperations(K key, RedisTemplate<K, V> template) {
super(key);
this.ops = template.zSetOps();
}
@Override
public boolean add(V value, double score) {
return ops.add(getKey(), value, score);
}
@Override
public RedisOperations<K, V> getOperations() {
return ops.getOperations();
}
@Override
public void intersectAndStore(K destKey, K... keys) {
ops.intersectAndStore(getKey(), destKey, keys);
}
@Override
public Set<V> range(int start, int end) {
return ops.range(getKey(), start, end);
}
@Override
public Set<V> rangeByScore(double min, double max) {
return ops.rangeByScore(getKey(), min, max);
}
@Override
public Integer rank(Object o) {
return ops.rank(getKey(), o);
}
@Override
public boolean remove(Object o) {
return ops.remove(getKey(), o);
}
@Override
public void removeRange(int start, int end) {
ops.removeRange(getKey(), start, end);
}
@Override
public void removeRangeByScore(double min, double max) {
ops.removeRangeByScore(getKey(), min, max);
}
@Override
public Set<V> reverseRange(int start, int end) {
return ops.reverseRange(getKey(), start, end);
}
@Override
public int size() {
return ops.size(getKey());
}
@Override
public void unionAndStore(K destKey, K... keys) {
ops.unionAndStore(getKey(), destKey, keys);
}
}

View File

@@ -13,33 +13,24 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.datastore.redis.connection;
package org.springframework.datastore.redis.core;
import org.springframework.datastore.redis.connection.RedisHashCommands.Entry;
/**
* Default {@link Entry} implementation.
* Default {@link KeyBound} implementation.
*
* @author Costin Leau
*/
public class DefaultEntry implements Entry {
public class DefaultKeyBound<K> implements KeyBound<K> {
private final String field;
private final String value;
private final K key;
public DefaultEntry(String field, String value) {
this.field = field;
this.value = value;
public DefaultKeyBound(K key) {
this.key = key;
}
@Override
public String getField() {
return null;
public K getKey() {
return key;
}
@Override
public String getValue() {
return null;
}
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2010 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.datastore.redis.core;
/**
* Redis store for a certain key. Useful for creating views into Redis 'collection' types.
*
* @author Costin Leau
*/
public interface KeyBound<K> {
/**
* Returns the key associated with this store.
*
* @return
*/
K getKey();
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.List;
/**
* Redis, list specific operations.
*
* @author Costin Leau
*/
public interface ListOperations<K, V> {
List<V> range(K key, int start, int end);
void trim(K key, int start, int end);
Integer length(K key);
Integer leftPush(K key, V value);
Integer rightPush(K key, V value);
void set(K key, int index, V value);
Integer remove(K key, int i, Object value);
V index(K key, int index);
V leftPop(K key);
V rightPop(K key);
List<V> blockingLeftPop(int timeout, K... keys);
List<V> blockingRightPop(int timeout, K... keys);
}

View File

@@ -46,6 +46,10 @@ public abstract class RedisConnectionUtils {
if (connHolder != null)
return connHolder.getConnection();
if (!allowCreate) {
throw new IllegalArgumentException("No connection found and allowCreate = false");
}
if (log.isDebugEnabled())
log.debug("Opening RedisConnection");
@@ -56,10 +60,9 @@ public abstract class RedisConnectionUtils {
TransactionSynchronizationManager.registerSynchronization(new RedisConnectionSynchronization(connHolder,
factory, true));
TransactionSynchronizationManager.bindResource(factory, connHolder);
return connHolder.getConnection();
}
return connHolder.getConnection();
return conn;
}
public static void releaseConnection(RedisConnection conn, RedisConnectionFactory factory) {

View File

@@ -15,12 +15,39 @@
*/
package org.springframework.datastore.redis.core;
/**
* Basic set of Redis operations, implemented by {@link RedisTemplate}.
*
* @author Costin Leau
*/
public interface RedisOperations {
public interface RedisOperations<K, V> {
void set(K key, V value);
V get(K key);
V getAndSet(K key, V newValue);
void watch(K... keys);
void multi();
Object exec();
Integer increment(K key, int delta);
void delete(K... keys);
ListOperations<K, V> listOps();
BoundListOperations<K, V> forList(K key);
SetOperations<K, V> setOps();
BoundSetOperations<K, V> forSet(K key);
ZSetOperations<K, V> zSetOps();
BoundZSetOperations<K, V> forZSet(K key);
}

View File

@@ -19,11 +19,17 @@ import java.lang.reflect.InvocationHandler;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set;
import org.springframework.datastore.redis.connection.RedisConnection;
import org.springframework.datastore.redis.connection.RedisConnectionFactory;
import org.springframework.datastore.redis.serializer.RedisSerializer;
import org.springframework.datastore.redis.serializer.SimpleRedisSerializer;
import org.springframework.datastore.redis.serializer.StringRedisSerializer;
import org.springframework.transaction.support.TransactionSynchronizationManager;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -43,10 +49,12 @@ import org.springframework.util.ClassUtils;
*
* @author Costin Leau
*/
public class RedisTemplate extends RedisAccessor {
public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperations<K, V> {
private boolean exposeConnection = false;
private RedisSerializer<Object> converter = new SimpleRedisSerializer<Object>();
private RedisSerializer keySerializer = new StringRedisSerializer();
private RedisSerializer valueSerializer = new SimpleRedisSerializer();
private RedisSerializer defaultSerializer = new SimpleRedisSerializer();
public RedisTemplate() {
}
@@ -60,7 +68,7 @@ public class RedisTemplate extends RedisAccessor {
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.del(redisKey);
connection.del(keySerializer.serialize(redisKey));
return null;
}
});
@@ -72,6 +80,10 @@ public class RedisTemplate extends RedisAccessor {
}
public <T> T execute(RedisCallback<T> action, boolean exposeConnection) {
return execute(action, isExposeConnection(), defaultSerializer);
}
public <T> T execute(RedisCallback<T> action, boolean exposeConnection, RedisSerializer returnSerializer) {
Assert.notNull(action, "Callback object must not be null");
RedisConnectionFactory factory = getConnectionFactory();
@@ -122,8 +134,16 @@ public class RedisTemplate extends RedisAccessor {
this.exposeConnection = exposeConnection;
}
public void setRedisConverter(RedisSerializer converter) {
this.converter = converter;
public void setKeySerializer(RedisSerializer serializer) {
this.keySerializer = serializer;
}
public void setValueSerializer(RedisSerializer serializer) {
this.valueSerializer = serializer;
}
public void setDefaultSerializer(RedisSerializer serializer) {
this.defaultSerializer = serializer;
}
/**
@@ -164,4 +184,642 @@ public class RedisTemplate extends RedisAccessor {
}
}
}
private byte[] rawKey(K key) {
return (key != null ? keySerializer.serialize(key) : null);
}
private <T> byte[] rawValue(T value) {
return (value != null ? valueSerializer.serialize(value) : null);
}
private byte[][] rawKeys(K... keys) {
final byte[][] rawKeys = new byte[keys.length][];
for (int i = 0; i < keys.length; i++) {
rawKeys[i] = rawKey(keys[i]);
}
return rawKeys;
}
@SuppressWarnings("unchecked")
private <T extends Collection<V>> T values(Collection<byte[]> rawValues, Class<? extends Collection> type) {
Collection<V> values = (List.class.isAssignableFrom(type) ? new ArrayList<V>(rawValues.size())
: new LinkedHashSet<V>(rawValues.size()));
for (byte[] bs : rawValues) {
values.add((V) valueSerializer.deserialize(bs));
}
return (T) values;
}
// utility methods for the template internal methods
private abstract class ValueDeserializingRedisCallback implements RedisCallback<V> {
private K key;
public ValueDeserializingRedisCallback() {
this(null);
}
public ValueDeserializingRedisCallback(K key) {
this.key = key;
}
@SuppressWarnings("unchecked")
@Override
public final V doInRedis(RedisConnection connection) throws Exception {
byte[] result = inRedis(rawKey(key), connection);
if (result != null) {
return (V) valueSerializer.deserialize(result);
}
return null;
}
protected abstract byte[] inRedis(byte[] rawKey, RedisConnection connection);
}
//
// RedisOperations
//
@Override
public Object exec() {
throw new UnsupportedOperationException();
}
@Override
public BoundListOperations<K, V> forList(K key) {
return new DefaultBoundListOperations<K, V>(key, this);
}
@Override
public V get(final K key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.get(rawKey);
}
}, false);
}
@Override
public V getAndSet(K key, V newValue) {
final byte[] rawValue = rawValue(newValue);
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.getSet(rawKey, rawValue);
}
}, false);
}
@Override
public Integer increment(K key, final int delta) {
final byte[] rawKey = rawKey(key);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
if (delta == 1) {
return connection.incr(rawKey);
}
if (delta == -1) {
return connection.decr(rawKey);
}
if (delta < 0) {
return connection.decrBy(rawKey, delta);
}
return connection.incrBy(rawKey, delta);
}
}, false);
}
@Override
public ListOperations<K, V> listOps() {
return new DefaultListOperations();
}
@Override
public void multi() {
throw new UnsupportedOperationException();
}
@Override
public void set(K key, V value) {
final byte[] rawValue = rawValue(value);
execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.set(rawKey, rawValue);
return null;
}
}, false);
}
@Override
public void watch(K... keys) {
final byte[][] rawKeys = rawKeys(keys);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.watch(rawKeys);
return null;
}
}, false);
}
@Override
public void delete(K... keys) {
final byte[][] rawKeys = rawKeys(keys);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.del(rawKeys);
return null;
}
}, false);
}
//
// List operations
//
private class DefaultListOperations implements ListOperations<K, V> {
@Override
public List<V> blockingLeftPop(final int timeout, K... keys) {
final byte[][] rawKeys = rawKeys(keys);
return execute(new RedisCallback<List<V>>() {
@Override
public List<V> doInRedis(RedisConnection connection) throws Exception {
return values(connection.bLPop(timeout, rawKeys), List.class);
}
}, false);
}
@Override
public List<V> blockingRightPop(final int timeout, K... keys) {
final byte[][] rawKeys = rawKeys(keys);
return execute(new RedisCallback<List<V>>() {
@Override
public List<V> doInRedis(RedisConnection connection) throws Exception {
return values(connection.bRPop(timeout, rawKeys), List.class);
}
}, false);
}
@Override
public V index(K key, final int index) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.lIndex(rawKey, index);
}
}, false);
}
@Override
public V leftPop(K key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.lPop(rawKey);
}
}, false);
}
@Override
public Integer leftPush(K key, V value) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.lPush(rawKey, rawValue);
}
}, false);
}
@Override
public Integer length(K key) {
final byte[] rawKey = rawKey(key);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.lLen(rawKey);
}
}, false);
}
@Override
public List<V> range(K key, final int start, final int end) {
final byte[] rawKey = rawKey(key);
return execute(new RedisCallback<List<V>>() {
@Override
public List<V> doInRedis(RedisConnection connection) throws Exception {
return values(connection.lRange(rawKey, start, end), List.class);
}
}, false);
}
@Override
public Integer remove(K key, final int count, Object value) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.lRem(rawKey, count, rawValue);
}
}, false);
}
@Override
public V rightPop(K key) {
return execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
return connection.rPop(rawKey);
}
}, false);
}
@Override
public Integer rightPush(K key, V value) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.rPush(rawKey, rawValue);
}
}, false);
}
@Override
public void set(K key, final int index, V value) {
final byte[] rawValue = rawValue(value);
execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.lSet(rawKey, index, rawValue);
return null;
}
}, false);
}
@Override
public void trim(K key, final int start, final int end) {
execute(new ValueDeserializingRedisCallback(key) {
@Override
protected byte[] inRedis(byte[] rawKey, RedisConnection connection) {
connection.lTrim(rawKey, start, end);
return null;
}
}, false);
}
}
//
// Set operations
//
private K[] aggregateKeys(K key, K... keys) {
Object[] aggregate = new Object[keys.length + 1];
aggregate[0] = key;
for (int i = 0; i < keys.length; i++) {
aggregate[i + 1] = keys[i];
}
return (K[]) aggregate;
}
@Override
public BoundSetOperations<K, V> forSet(K key) {
return new DefaultBoundSetOperations<K, V>(key, this);
}
@Override
public SetOperations<K, V> setOps() {
return new DefaultSetOperations();
}
private class DefaultSetOperations implements SetOperations<K, V> {
@Override
public Boolean add(K key, V value) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws Exception {
return connection.sAdd(rawKey, rawValue);
}
}, false);
}
@Override
public Set<V> diff(final K key, final K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.sDiff(rawKeys);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public void diffAndStore(K destKey, final K key, final K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
final byte[] rawDestKey = rawKey(destKey);
Object rawValues = execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.sDiffStore(rawDestKey, rawKeys);
return null;
}
}, false);
}
@Override
public RedisOperations<K, V> getOperations() {
return RedisTemplate.this;
}
@Override
public Set<V> intersect(K key, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.sInter(rawKeys);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public void intersectAndStore(K key, K destKey, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
final byte[] rawDestKey = rawKey(destKey);
Object rawValues = execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.sInterStore(rawDestKey, rawKeys);
return null;
}
}, false);
}
@Override
public boolean isMember(K key, Object o) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(o);
return execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws Exception {
return connection.sIsMember(rawKey, rawValue);
}
}, false);
}
@Override
public Set<V> members(K key) {
final byte[] rawKey = rawKey(key);
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.sMembers(rawKey);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public boolean remove(K key, Object o) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(o);
return execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws Exception {
return connection.sRem(rawKey, rawValue);
}
}, false);
}
@Override
public int size(K key) {
final byte[] rawKey = rawKey(key);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.sCard(rawKey);
}
}, false);
}
@Override
public Set<V> union(K key, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.sUnion(rawKeys);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public void unionAndStore(K key, K destKey, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
final byte[] rawDestKey = rawKey(destKey);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.sUnionStore(rawDestKey, rawKeys);
return null;
}
}, false);
}
}
//
// ZSet operations
//
@Override
public BoundZSetOperations<K, V> forZSet(K key) {
return new DefaultBoundZSetOperations<K, V>(key, this);
}
@Override
public ZSetOperations<K, V> zSetOps() {
return new DefaultZSetOperations();
}
private class DefaultZSetOperations implements ZSetOperations<K, V> {
@Override
public boolean add(final K key, final V value, final double score) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(value);
return execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws Exception {
return connection.zAdd(rawKey, score, rawValue);
}
}, false);
}
@Override
public RedisOperations<K, V> getOperations() {
return RedisTemplate.this;
}
@Override
public void intersectAndStore(K key, K destKey, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
final byte[] rawDestKey = rawKey(destKey);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.zInterStore(rawDestKey, rawKeys);
return null;
}
}, false);
}
@Override
public Set<V> range(K key, final int start, final int end) {
final byte[] rawKey = rawKey(key);
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.zRange(rawKey, start, end);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public Set<V> rangeByScore(K key, final double min, final double max) {
final byte[] rawKey = rawKey(key);
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.zRangeByScore(rawKey, min, max);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public Integer rank(K key, Object o) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(o);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.zRank(rawKey, rawValue);
}
}, false);
}
@Override
public boolean remove(K key, Object o) {
final byte[] rawKey = rawKey(key);
final byte[] rawValue = rawValue(o);
return execute(new RedisCallback<Boolean>() {
@Override
public Boolean doInRedis(RedisConnection connection) throws Exception {
return connection.zRem(rawKey, rawValue);
}
}, false);
}
@Override
public void removeRange(K key, final int start, final int end) {
final byte[] rawKey = rawKey(key);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.zRemRange(rawKey, start, end);
return null;
}
}, false);
}
@Override
public void removeRangeByScore(K key, final double min, final double max) {
final byte[] rawKey = rawKey(key);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.zRemRangeByScore(rawKey, min, max);
return null;
}
}, false);
}
@Override
public Set<V> reverseRange(K key, final int start, final int end) {
final byte[] rawKey = rawKey(key);
Set<byte[]> rawValues = execute(new RedisCallback<Set<byte[]>>() {
@Override
public Set<byte[]> doInRedis(RedisConnection connection) throws Exception {
return connection.zRevRange(rawKey, start, end);
}
}, false);
return values(rawValues, Set.class);
}
@Override
public int size(K key) {
final byte[] rawKey = rawKey(key);
return execute(new RedisCallback<Integer>() {
@Override
public Integer doInRedis(RedisConnection connection) throws Exception {
return connection.zCard(rawKey);
}
}, false);
}
@Override
public void unionAndStore(K key, K destKey, K... keys) {
final byte[][] rawKeys = rawKeys(aggregateKeys(key, keys));
final byte[] rawDestKey = rawKey(destKey);
execute(new RedisCallback<Object>() {
@Override
public Object doInRedis(RedisConnection connection) throws Exception {
connection.zUnionStore(rawDestKey, rawKeys);
return null;
}
}, false);
}
}
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* Redis set specific operations.
*
* @author Costin Leau
*/
public interface SetOperations<K, V> {
Set<V> diff(K key, K... keys);
void diffAndStore(K key, K destKey, K... keys);
RedisOperations<K, V> getOperations();
Set<V> intersect(K key, K... keys);
void intersectAndStore(K key, K destKey, K... keys);
Set<V> union(K key, K... keys);
void unionAndStore(K key, K destKey, K... keys);
Boolean add(K key, V value);
boolean isMember(K key, Object o);
Set<V> members(K key);
boolean remove(K key, Object o);
int size(K key);
}

View File

@@ -0,0 +1,51 @@
/*
* Copyright 2010 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.datastore.redis.core;
import java.util.Set;
/**
* Redis ZSet/sorted set specific operations.
*
* @author Costin Leau
*/
public interface ZSetOperations<K, V> {
void intersectAndStore(K key, K destKey, K... keys);
Set<V> range(K key, int start, int end);
Set<V> rangeByScore(K key, double min, double max);
void removeRange(K key, int start, int end);
void removeRangeByScore(K key, double min, double max);
void unionAndStore(K key, K destKey, K... keys);
boolean add(K key, V value, double score);
Integer rank(K key, Object o);
boolean remove(K key, Object o);
int size(K key);
Set<V> reverseRange(K key, int start, int end);
RedisOperations<K, V> getOperations();
}

View File

@@ -23,7 +23,7 @@ package org.springframework.datastore.redis.serializer;
*/
public interface RedisSerializer<T> {
byte[] serialize(T object);
byte[] serialize(T t);
T deserialize(byte[] bytes);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.datastore.redis.serializer;
import org.springframework.core.convert.converter.Converter;
import org.springframework.core.serializer.support.DeserializingConverter;
import org.springframework.core.serializer.support.SerializingConverter;
import org.springframework.datastore.redis.UncategorizedRedisException;
/**
* Simple Redis serializer delegating to the default serializer in Spring 3.
@@ -25,18 +26,30 @@ import org.springframework.core.serializer.support.SerializingConverter;
* @author Mark Pollack
* @author Costin Leau
*/
public class SimpleRedisSerializer<T> implements RedisSerializer<T> {
public class SimpleRedisSerializer implements RedisSerializer<Object> {
private Converter<Object, byte[]> serializer = new SerializingConverter();
private Converter<byte[], Object> deserializer = new DeserializingConverter();
private sun.misc.BASE64Encoder encoder = new sun.misc.BASE64Encoder();
private sun.misc.BASE64Decoder decoder = new sun.misc.BASE64Decoder();
@SuppressWarnings("unchecked")
@Override
public T deserialize(byte[] bytes) {
return (T) deserializer.convert(bytes);
public Object deserialize(byte[] bytes) {
try {
return deserializer.convert(bytes);
} catch (Exception ex) {
throw new UncategorizedRedisException("Cannot deserialize", ex);
}
}
@Override
public byte[] serialize(T object) {
return serializer.convert(object);
public byte[] serialize(Object object) {
try {
return serializer.convert(object);
} catch (Exception ex) {
throw new UncategorizedRedisException("Cannot serialize", ex);
}
}
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2010 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.datastore.redis.serializer;
import java.nio.charset.Charset;
/**
* Simple String to byte[] (and back) serializer. Relies on the specified charset
* to properly convert the String into bytes and vice-versa.
*
* @author Costin Leau
*/
public class StringRedisSerializer implements RedisSerializer<String> {
private final Charset charset;
public StringRedisSerializer() {
this(Charset.forName("UTF8"));
}
public StringRedisSerializer(Charset charset) {
this.charset = charset;
}
@Override
public String deserialize(byte[] bytes) {
return new String(bytes, charset);
}
@Override
public byte[] serialize(String object) {
return object.toString().getBytes(charset);
}
}

View File

@@ -18,21 +18,23 @@ package org.springframework.datastore.redis.util;
import java.util.AbstractCollection;
import java.util.Collection;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Base implementation for Redis collections.
*
* @author Costin Leau
*/
public abstract class AbstractRedisCollection extends AbstractCollection<String> implements RedisStore {
public abstract class AbstractRedisCollection<E> extends AbstractCollection<E> implements RedisStore<String> {
public static final String ENCODING = "UTF-8";
protected final String key;
protected final RedisCommands commands;
protected final RedisOperations<String, E> operations;
public AbstractRedisCollection(String key, RedisCommands commands) {
public <K> AbstractRedisCollection(String key, RedisOperations<String, E> operations) {
this.key = key;
this.commands = commands;
this.operations = operations;
}
@Override
@@ -41,15 +43,20 @@ public abstract class AbstractRedisCollection extends AbstractCollection<String>
}
@Override
public boolean addAll(Collection<? extends String> c) {
public RedisOperations<String, E> getOperations() {
return operations;
}
@Override
public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (String string : c) {
modified |= add(string);
for (E e : c) {
modified |= add(e);
}
return modified;
}
public abstract boolean add(String e);
public abstract boolean add(E e);
public abstract void clear();
@@ -78,4 +85,34 @@ public abstract class AbstractRedisCollection extends AbstractCollection<String>
throw new UnsupportedOperationException();
}
@Override
public boolean equals(Object o) {
if (o == this)
return true;
if (o instanceof RedisStore) {
return key.equals(((RedisStore) o).getKey());
}
if (o instanceof AbstractRedisCollection) {
return o.hashCode() == hashCode();
}
return false;
}
@Override
public int hashCode() {
int result = 17 + getClass().hashCode();
result = result * 31 + key.hashCode();
return result;
}
@Override
public String toString() {
StringBuilder sb = new StringBuilder();
sb.append("RedisStore for key:");
sb.append(getKey());
return sb.toString();
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2010 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.datastore.redis.util;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
/**
* Utility class used mainly for type conversion by the default collection implementations.
*
* @author Costin Leau
*/
abstract class CollectionUtils {
@SuppressWarnings("unchecked")
static <E> Collection<E> reverse(Collection<? extends E> c) {
Object[] reverse = new Object[c.size()];
int index = c.size();
for (E e : c) {
reverse[--index] = e;
}
return (List<E>) Arrays.asList(reverse);
}
}

View File

@@ -21,98 +21,133 @@ import java.util.List;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.ListOperations;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Default implementation for {@link RedisList}.
*
* @author Costin Leau
*/
public class DefaultRedisList extends AbstractRedisCollection implements RedisList {
public class DefaultRedisList<E> extends AbstractRedisCollection<E> implements RedisList<E> {
private class DefaultRedisListIterator extends RedisIterator {
private final ListOperations<String, E> listOps;
public DefaultRedisListIterator(Iterator<String> delegate) {
private class DefaultRedisListIterator<E> extends RedisIterator<E> {
public DefaultRedisListIterator(Iterator<E> delegate) {
super(delegate);
}
@Override
protected void removeFromRedisStorage(String item) {
protected void removeFromRedisStorage(E item) {
DefaultRedisList.this.remove(item);
}
}
public DefaultRedisList(String key, RedisCommands commands) {
super(key, commands);
public DefaultRedisList(String key, RedisOperations<String, E> operations) {
super(key, operations);
listOps = operations.listOps();
}
@Override
public List<String> range(int start, int end) {
return commands.lRange(key, start, end);
public List<E> range(int start, int end) {
return listOps.range(key, start, end);
}
@Override
public RedisList trim(int start, int end) {
commands.lTrim(key, start, end);
public RedisList<E> trim(int start, int end) {
listOps.trim(key, start, end);
return this;
}
private List<String> content() {
return commands.lRange(key, 0, -1);
private List<E> content() {
return listOps.range(key, 0, -1);
}
@Override
public Iterator<String> iterator() {
public Iterator<E> iterator() {
return content().iterator();
}
@Override
public int size() {
return commands.lLen(key);
return listOps.length(key);
}
@Override
public boolean add(String value) {
commands.rPush(key, value);
public boolean add(E value) {
listOps.rightPush(key, value);
return true;
}
@Override
public void clear() {
commands.lTrim(key, 0, -1);
listOps.trim(key, size() + 1, 0);
}
@Override
public boolean remove(Object o) {
Integer result = commands.lRem(key, 0, o.toString());
Integer result = listOps.remove(key, 0, o);
return (result != null && result.intValue() > 0);
}
@Override
public void add(int index, String element) {
public void add(int index, E element) {
if (index == 0) {
commands.lPush(key, element);
listOps.leftPush(key, element);
return;
}
else if (index == size()) {
commands.rPush(key, element);
int size = size();
if (index == size()) {
listOps.rightPush(key, element);
return;
}
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
}
throw new IllegalArgumentException("Redis supports insertion only at the beginning or the end of the list");
}
@Override
public boolean addAll(int index, Collection<? extends String> c) {
for (String string : c) {
add(index, string);
public boolean addAll(int index, Collection<? extends E> c) {
// insert collection in reverse
if (index == 0) {
Collection<? extends E> reverseC = CollectionUtils.reverse(c);
for (E e : reverseC) {
listOps.leftPush(key, e);
}
return true;
}
return true;
int size = size();
if (index == size()) {
for (E e : c) {
listOps.rightPush(key, e);
}
return true;
}
if (index < 0 || index > size) {
throw new IndexOutOfBoundsException();
}
throw new IllegalArgumentException("Redis supports insertion only at the beginning or the end of the list");
}
@Override
public String get(int index) {
return commands.lIndex(key, index);
public E get(int index) {
if (index < 0 || index > size()) {
throw new IndexOutOfBoundsException();
}
return listOps.index(key, index);
}
@Override
@@ -126,37 +161,37 @@ public class DefaultRedisList extends AbstractRedisCollection implements RedisLi
}
@Override
public ListIterator<String> listIterator() {
public ListIterator<E> listIterator() {
throw new UnsupportedOperationException();
}
@Override
public ListIterator<String> listIterator(int index) {
public ListIterator<E> listIterator(int index) {
throw new UnsupportedOperationException();
}
@Override
public String remove(int index) {
public E remove(int index) {
throw new UnsupportedOperationException();
}
@Override
public String set(int index, String element) {
String object = get(index);
commands.lSet(key, index, element);
public E set(int index, E e) {
E object = get(index);
listOps.set(key, index, e);
return object;
}
@Override
public List<String> subList(int fromIndex, int toIndex) {
public List<E> subList(int fromIndex, int toIndex) {
throw new UnsupportedOperationException();
}
@Override
public String element() {
String value = peek();
public E element() {
E value = peek();
if (value == null)
throw new NoSuchElementException();
@@ -165,27 +200,29 @@ public class DefaultRedisList extends AbstractRedisCollection implements RedisLi
@Override
public boolean offer(String e) {
commands.lPush(key, e);
public boolean offer(E e) {
listOps.leftPush(key, e);
return true;
}
@Override
public String peek() {
return commands.lIndex(key, 0);
public E peek() {
E element = listOps.index(key, 0);
return (element == null ? null : element);
}
@Override
public String poll() {
return commands.lPop(key);
public E poll() {
E element = listOps.leftPop(key);
return (element == null ? null : element);
}
@Override
public String remove() {
String value = poll();
public E remove() {
E value = poll();
if (value == null)
throw new NoSuchElementException();

View File

@@ -21,13 +21,14 @@ import java.util.Map;
import java.util.Set;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Default {@link RedisMap} implementation.
*
* @author Costin Leau
*/
public class DefaultRedisMap implements RedisMap {
public class DefaultRedisMap<K, V> implements RedisMap<K, V> {
private class DefaultRedisMapEntry implements Map.Entry<String, String> {
@@ -60,17 +61,25 @@ public class DefaultRedisMap implements RedisMap {
}
protected final String redisKey;
protected final RedisCommands commands;
protected final RedisOperations<String, ?> operations;
private final MapOperations<String, K, V> mapOps;
/**
* Constructs a new <code>DefaultRedisMap</code> instance.
*
* @param key
* @param commands
* @param operations
*/
public DefaultRedisMap(String key, RedisCommands commands) {
public DefaultRedisMap(String key, RedisOperations<K, V> operations) {
this.redisKey = key;
this.commands = commands;
this.operations = operations;
this.maps = operations.forMap(key);
}
public DefaultRedisList(String key, RedisOperations<String, E> operations) {
super(key, operations);
listOps = operations.listOps();
}
@Override
@@ -88,6 +97,11 @@ public class DefaultRedisMap implements RedisMap {
return redisKey;
}
@Override
public RedisCommands getOperations() {
return commands;
}
@Override
public void clear() {
throw new UnsupportedOperationException();

View File

@@ -18,23 +18,26 @@ package org.springframework.datastore.redis.util;
import java.util.Iterator;
import java.util.Set;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.BoundSetOperations;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Default implementation for {@link RedisSet}.
*
* @author Costin Leau
*/
public class DefaultRedisSet extends AbstractRedisCollection implements RedisSet {
public class DefaultRedisSet<E> extends AbstractRedisCollection<E> implements RedisSet<E> {
private class DefaultRedisSetIterator extends RedisIterator {
private final BoundSetOperations<String, E> boundSetOps;
public DefaultRedisSetIterator(Iterator<String> delegate) {
private class DefaultRedisSetIterator extends RedisIterator<E> {
public DefaultRedisSetIterator(Iterator<E> delegate) {
super(delegate);
}
@Override
protected void removeFromRedisStorage(String item) {
protected void removeFromRedisStorage(E item) {
DefaultRedisSet.this.remove(item);
}
}
@@ -43,82 +46,92 @@ public class DefaultRedisSet extends AbstractRedisCollection implements RedisSet
* Constructs a new <code>DefaultRedisSet</code> instance.
*
* @param key
* @param commands
* @param operations
*/
public DefaultRedisSet(String key, RedisCommands commands) {
super(key, commands);
public DefaultRedisSet(String key, RedisOperations<String, E> operations) {
super(key, operations);
boundSetOps = operations.forSet(key);
}
/**
* Constructs a new <code>DefaultRedisSet</code> instance.
*
* @param boundOps
*/
public DefaultRedisSet(BoundSetOperations<String, E> boundOps) {
super(boundOps.getKey(), boundOps.getOperations());
this.boundSetOps = boundOps;
}
@Override
public Set<String> diff(RedisSet... sets) {
return commands.sDiff(extractKeys(sets));
public Set<E> diff(RedisSet<? extends E>... sets) {
return boundSetOps.diff(extractKeys(sets));
}
@Override
public RedisSet diffAndStore(String destKey, RedisSet... sets) {
commands.sDiffStore(destKey, extractKeys(sets));
return new DefaultRedisSet(destKey, commands);
public RedisSet<E> diffAndStore(String destKey, RedisSet<? extends E>... sets) {
boundSetOps.diffAndStore(destKey, extractKeys(sets));
return new DefaultRedisSet(boundSetOps.getOperations().forSet(destKey));
}
@Override
public Set<String> intersect(RedisSet... sets) {
return commands.sInter(extractKeys(sets));
public Set<E> intersect(RedisSet<? extends E>... sets) {
return boundSetOps.intersect(extractKeys(sets));
}
@Override
public RedisSet intersectAndStore(String destKey, RedisSet... sets) {
commands.sInterStore(destKey, extractKeys(sets));
return new DefaultRedisSet(destKey, commands);
public RedisSet<E> intersectAndStore(String destKey, RedisSet<? extends E>... sets) {
boundSetOps.intersectAndStore(destKey, extractKeys(sets));
return new DefaultRedisSet(boundSetOps.getOperations().forSet(destKey));
}
@Override
public Set<String> union(RedisSet... sets) {
return commands.sUnion(extractKeys(sets));
public Set<E> union(RedisSet<? extends E>... sets) {
return boundSetOps.union(extractKeys(sets));
}
@Override
public RedisSet unionAndStore(String destKey, RedisSet... sets) {
commands.sUnionStore(destKey, extractKeys(sets));
return new DefaultRedisSet(destKey, commands);
public RedisSet<E> unionAndStore(String destKey, RedisSet<? extends E>... sets) {
boundSetOps.unionAndStore(destKey, extractKeys(sets));
return new DefaultRedisSet(boundSetOps.getOperations().forSet(destKey));
}
@Override
public boolean add(String e) {
return commands.sAdd(key, e);
public boolean add(E e) {
return boundSetOps.add(e);
}
@Override
public void clear() {
// intersect the set with a non existing one
// TODO: find a safer way to clean the set
commands.sInterStore(key, key, "NON-EXISTING");
boundSetOps.intersectAndStore(key, "NON-EXISTING");
}
@Override
public boolean contains(Object o) {
return commands.sIsMember(key, o.toString());
return boundSetOps.isMember(o);
}
@Override
public Iterator<String> iterator() {
return new DefaultRedisSetIterator(commands.sMembers(key).iterator());
public Iterator<E> iterator() {
return new DefaultRedisSetIterator(boundSetOps.members().iterator());
}
@Override
public boolean remove(Object o) {
return commands.sRem(key, o.toString());
return boundSetOps.remove(o);
}
@Override
public int size() {
return commands.sCard(key);
return boundSetOps.size();
}
private String[] extractKeys(RedisSet... sets) {
private String[] extractKeys(RedisSet<?>... sets) {
String[] keys = new String[sets.length + 1];
keys[0] = key;
for (int i = 0; i < keys.length; i++) {
keys[i + 1] = sets[i].getKey();
keys[i] = sets[i].getKey();
}
return keys;

View File

@@ -20,126 +20,142 @@ import java.util.Iterator;
import java.util.Set;
import java.util.SortedSet;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.BoundZSetOperations;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Default implementation for {@link RedisSortedSet}.
*
* @author Costin Leau
*/
class DefaultRedisSortedSet extends AbstractRedisCollection implements RedisSortedSet {
class DefaultRedisSortedSet<E> extends AbstractRedisCollection<E> implements RedisSortedSet<E> {
private class DefaultRedisSortedSetIterator extends RedisIterator {
private final BoundZSetOperations<String, E> boundZSetOps;
private class DefaultRedisSortedSetIterator extends RedisIterator<E> {
public DefaultRedisSortedSetIterator(Iterator<String> delegate) {
public DefaultRedisSortedSetIterator(Iterator<E> delegate) {
super(delegate);
}
@Override
protected void removeFromRedisStorage(String item) {
protected void removeFromRedisStorage(E item) {
DefaultRedisSortedSet.this.remove(item);
}
}
public DefaultRedisSortedSet(String key, RedisCommands commands) {
super(key, commands);
/**
* Constructs a new <code>DefaultRedisSortedSet</code> instance.
*
* @param key
* @param operations
*/
public DefaultRedisSortedSet(String key, RedisOperations<String, E> operations) {
super(key, operations);
boundZSetOps = operations.forZSet(key);
}
public DefaultRedisSortedSet(BoundZSetOperations<String, E> boundOps) {
super(boundOps.getKey(), boundOps.getOperations());
this.boundZSetOps = boundOps;
}
@Override
public RedisSortedSet intersectAndStore(String destKey, RedisSortedSet... sets) {
commands.zInterStore(destKey, extractKeys(sets));
return new DefaultRedisSortedSet(destKey, commands);
public RedisSortedSet<E> intersectAndStore(String destKey, RedisSortedSet<E>... sets) {
boundZSetOps.intersectAndStore(destKey, extractKeys(sets));
return new DefaultRedisSortedSet<E>(boundZSetOps.getOperations().forZSet(destKey));
}
@Override
public Set<String> range(int start, int end) {
return commands.zRange(key, start, end);
public Set<E> range(int start, int end) {
return boundZSetOps.range(start, end);
}
@Override
public Set<String> rangeByScore(double min, double max) {
return commands.zRangeByScore(key, min, max);
public Set<E> rangeByScore(double min, double max) {
return boundZSetOps.rangeByScore(min, max);
}
@Override
public RedisSortedSet remove(int start, int end) {
commands.zRemRange(key, start, end);
public RedisSortedSet<E> remove(int start, int end) {
boundZSetOps.removeRange(start, end);
return this;
}
@Override
public RedisSortedSet removeByScore(double min, double max) {
commands.zRemRangeByScore(key, min, max);
public RedisSortedSet<E> removeByScore(double min, double max) {
boundZSetOps.removeRangeByScore(min, max);
return this;
}
@Override
public RedisSortedSet unionAndStore(String destKey, RedisSortedSet... sets) {
commands.zUnionStore(destKey, extractKeys(sets));
return new DefaultRedisSortedSet(destKey, commands);
public RedisSortedSet<E> unionAndStore(String destKey, RedisSortedSet<E>... sets) {
boundZSetOps.unionAndStore(destKey, extractKeys(sets));
return new DefaultRedisSortedSet<E>(boundZSetOps.getOperations().forZSet(destKey));
}
@Override
public boolean add(String e) {
return commands.zAdd(key, 0, e);
public boolean add(E e) {
return boundZSetOps.add(e, 0);
}
@Override
public void clear() {
commands.zRemRange(key, 0, -1);
boundZSetOps.removeRange(0, -1);
}
@Override
public boolean contains(Object o) {
return (commands.zRank(key, o.toString()) != null);
return (boundZSetOps.rank(o) != null);
}
@Override
public Iterator<String> iterator() {
return new DefaultRedisSortedSetIterator(commands.zRange(key, 0, -1).iterator());
public Iterator<E> iterator() {
return new DefaultRedisSortedSetIterator(boundZSetOps.range(0, -1).iterator());
}
@Override
public boolean remove(Object o) {
return commands.zRem(key, o.toString());
return boundZSetOps.remove(o);
}
@Override
public int size() {
return commands.zCard(key);
return boundZSetOps.size();
}
@Override
public Comparator<? super String> comparator() {
public Comparator<? super E> comparator() {
return null;
}
@Override
public String first() {
return commands.zRange(key, 0, 0).iterator().next();
public E first() {
return boundZSetOps.range(0, 0).iterator().next();
}
@Override
public SortedSet<String> headSet(String toElement) {
public SortedSet<E> headSet(E toElement) {
throw new UnsupportedOperationException();
}
@Override
public String last() {
return commands.zRevRange(key, 0, 0).iterator().next();
public E last() {
return boundZSetOps.reverseRange(0, 0).iterator().next();
}
@Override
public SortedSet<String> subSet(String fromElement, String toElement) {
public SortedSet<E> subSet(E fromElement, E toElement) {
throw new UnsupportedOperationException();
}
@Override
public SortedSet<String> tailSet(String fromElement) {
public SortedSet<E> tailSet(E fromElement) {
throw new UnsupportedOperationException();
}
private String[] extractKeys(RedisSortedSet... sets) {
private String[] extractKeys(RedisSortedSet<E>... sets) {
String[] keys = new String[sets.length + 1];
keys[0] = key;
for (int i = 0; i < keys.length; i++) {

View File

@@ -17,43 +17,41 @@ package org.springframework.datastore.redis.util;
import java.io.Serializable;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Atomic integer backed by Redis.
* Uses Redis atomic increment/decrement and watch/multi/exec commands for CAS operations.
* Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS operations.
*
* @see java.util.concurrent.atomic.AtomicInteger
* @author Costin Leau
*/
public class RedisAtomicInteger extends Number implements Serializable {
private static final long serialVersionUID = 5984507176128031015L;
private final String key;
private RedisCommands commands;
private RedisOperations<String, Integer> operations;
/**
* Constructs a new <code>RedisAtomicInteger</code> instance with an initial value of zero.
*
* @param redisCounter
* @param commands
* @param operations
*/
public RedisAtomicInteger(String redisCounter, RedisCommands commands) {
this(redisCounter, commands, 0);
public RedisAtomicInteger(String redisCounter, RedisOperations<String, Integer> operations) {
this(redisCounter, operations, 0);
}
/**
* Constructs a new <code>RedisAtomicInteger</code> instance with the given initial value.
*
* @param redisCounter
* @param commands
* @param operations
* @param initialValue
*/
public RedisAtomicInteger(String redisCounter, RedisCommands commands, int initialValue) {
public RedisAtomicInteger(String redisCounter, RedisOperations<String, Integer> operations, int initialValue) {
this.key = redisCounter;
this.commands = commands;
commands.set(redisCounter, Integer.toString(initialValue));
this.operations = operations;
operations.set(redisCounter, initialValue);
}
/**
@@ -62,7 +60,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @return the current value
*/
public int get() {
return Integer.valueOf(commands.get(key));
return Integer.valueOf(operations.get(key));
}
/**
@@ -71,7 +69,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @param newValue the new value
*/
public void set(int newValue) {
commands.set(key, Integer.toString(newValue));
operations.set(key, newValue);
}
/**
@@ -81,7 +79,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @return the previous value
*/
public int getAndSet(int newValue) {
return Integer.valueOf(commands.getSet(key, Integer.toString(newValue)));
return operations.getAndSet(key, newValue);
}
/**
@@ -94,11 +92,11 @@ public class RedisAtomicInteger extends Number implements Serializable {
*/
public boolean compareAndSet(int expect, int update) {
for (;;) {
commands.watch(key);
operations.watch(key);
if (expect == get()) {
commands.multi();
operations.multi();
set(update);
if (commands.exec() != null) {
if (operations.exec() != null) {
return true;
}
}
@@ -112,11 +110,11 @@ public class RedisAtomicInteger extends Number implements Serializable {
*/
public int getAndIncrement() {
for (;;) {
commands.watch(key);
operations.watch(key);
int value = get();
commands.multi();
commands.incr(key);
if (commands.exec() != null) {
operations.multi();
operations.increment(key, 1);
if (operations.exec() != null) {
return value;
}
}
@@ -129,11 +127,11 @@ public class RedisAtomicInteger extends Number implements Serializable {
*/
public int getAndDecrement() {
for (;;) {
commands.watch(key);
operations.watch(key);
int value = get();
commands.multi();
commands.decr(key);
if (commands.exec() != null) {
operations.multi();
operations.increment(key, -1);
if (operations.exec() != null) {
return value;
}
}
@@ -147,11 +145,11 @@ public class RedisAtomicInteger extends Number implements Serializable {
*/
public int getAndAdd(int delta) {
for (;;) {
commands.watch(key);
operations.watch(key);
int value = get();
commands.multi();
operations.multi();
set(value + delta);
if (commands.exec() != null) {
if (operations.exec() != null) {
return value;
}
}
@@ -162,7 +160,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @return the updated value
*/
public int incrementAndGet() {
return commands.incr(key);
return operations.increment(key, 1);
}
/**
@@ -170,7 +168,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @return the updated value
*/
public int decrementAndGet() {
return commands.decr(key);
return operations.increment(key, -1);
}
@@ -180,7 +178,7 @@ public class RedisAtomicInteger extends Number implements Serializable {
* @return the updated value
*/
public int addAndGet(int delta) {
return commands.incrBy(key, delta);
return operations.increment(key, delta);
}
/**

View File

@@ -17,11 +17,11 @@ package org.springframework.datastore.redis.util;
import java.io.Serializable;
import org.springframework.datastore.redis.connection.RedisCommands;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Atomic long backed by Redis.
* Uses Redis atomic increment/decrement and watch/multi/exec commands for CAS operations.
* Uses Redis atomic increment/decrement and watch/multi/exec operations for CAS operations.
*
* @see java.util.concurrent.atomic.AtomicLong
* @author Costin Leau
@@ -29,29 +29,29 @@ import org.springframework.datastore.redis.connection.RedisCommands;
public class RedisAtomicLong extends Number implements Serializable {
private final String key;
private RedisCommands commands;
private RedisOperations<String, Long> operations;
/**
* Constructs a new <code>RedisAtomicLong</code> instance with an initial value of zero.
*
* @param redisCounter
* @param commands
* @param operations
*/
public RedisAtomicLong(String redisCounter, RedisCommands commands) {
this(redisCounter, commands, 0);
public RedisAtomicLong(String redisCounter, RedisOperations<String, Long> operations) {
this(redisCounter, operations, 0);
}
/**
* Constructs a new <code>RedisAtomicLong</code> instance with the given initial value.
*
* @param redisCounter
* @param commands
* @param operations
* @param initialValue
*/
public RedisAtomicLong(String redisCounter, RedisCommands commands, long initialValue) {
public RedisAtomicLong(String redisCounter, RedisOperations<String, Long> operations, long initialValue) {
this.key = redisCounter;
this.commands = commands;
commands.set(redisCounter, Long.toString(initialValue));
this.operations = operations;
operations.set(redisCounter, initialValue);
}
/**
@@ -60,7 +60,7 @@ public class RedisAtomicLong extends Number implements Serializable {
* @return the current value
*/
public long get() {
return Long.valueOf(commands.get(key));
return operations.get(key);
}
/**
@@ -69,7 +69,7 @@ public class RedisAtomicLong extends Number implements Serializable {
* @param newValue the new value
*/
public void set(long newValue) {
commands.set(key, Long.toString(newValue));
operations.set(key, newValue);
}
/**
@@ -79,7 +79,7 @@ public class RedisAtomicLong extends Number implements Serializable {
* @return the previous value
*/
public long getAndSet(long newValue) {
return Long.valueOf(commands.getSet(key, Long.toString(newValue)));
return operations.getAndSet(key, newValue);
}
/**
@@ -93,11 +93,11 @@ public class RedisAtomicLong extends Number implements Serializable {
*/
public boolean compareAndSet(long expect, long update) {
for (;;) {
commands.watch(key);
operations.watch(key);
if (expect == get()) {
commands.multi();
operations.multi();
set(update);
if (commands.exec() != null) {
if (operations.exec() != null) {
return true;
}
}
@@ -112,11 +112,11 @@ public class RedisAtomicLong extends Number implements Serializable {
*/
public long getAndIncrement() {
for (;;) {
commands.watch(key);
operations.watch(key);
long value = get();
commands.multi();
commands.incr(key);
if (commands.exec() != null) {
operations.multi();
operations.increment(key, 1);
if (operations.exec() != null) {
return value;
}
}
@@ -129,11 +129,11 @@ public class RedisAtomicLong extends Number implements Serializable {
*/
public long getAndDecrement() {
for (;;) {
commands.watch(key);
operations.watch(key);
long value = get();
commands.multi();
commands.decr(key);
if (commands.exec() != null) {
operations.multi();
operations.increment(key, -1);
if (operations.exec() != null) {
return value;
}
}
@@ -147,11 +147,11 @@ public class RedisAtomicLong extends Number implements Serializable {
*/
public long getAndAdd(long delta) {
for (;;) {
commands.watch(key);
operations.watch(key);
long value = get();
commands.multi();
operations.multi();
set(value + delta);
if (commands.exec() != null) {
if (operations.exec() != null) {
return value;
}
}
@@ -163,7 +163,7 @@ public class RedisAtomicLong extends Number implements Serializable {
* @return the updated value
*/
public long incrementAndGet() {
return commands.incr(key);
return operations.increment(key, 1);
}
/**
@@ -172,7 +172,7 @@ public class RedisAtomicLong extends Number implements Serializable {
* @return the updated value
*/
public long decrementAndGet() {
return commands.decr(key);
return operations.increment(key, -1);
}
/**
@@ -183,11 +183,12 @@ public class RedisAtomicLong extends Number implements Serializable {
*/
public long addAndGet(long delta) {
// TODO: is this really safe
return commands.incrBy(key, (int) delta);
return operations.increment(key, (int) delta);
}
/**
* Returns the String representation of the current value.
*
* @return the String representation of the current value.
*/
public String toString() {

View File

@@ -22,18 +22,18 @@ import java.util.Iterator;
*
* @author Costin Leau
*/
abstract class RedisIterator implements Iterator<String> {
abstract class RedisIterator<E> implements Iterator<E> {
private final Iterator<String> delegate;
private final Iterator<E> delegate;
private String item;
private E item;
/**
* Constructs a new <code>RedisIterator</code> instance.
*
* @param delegate
*/
RedisIterator(Iterator<String> delegate) {
RedisIterator(Iterator<E> delegate) {
this.delegate = delegate;
}
@@ -49,7 +49,7 @@ abstract class RedisIterator implements Iterator<String> {
* @return
* @see java.util.Iterator#next()
*/
public String next() {
public E next() {
item = delegate.next();
return item;
}
@@ -64,5 +64,5 @@ abstract class RedisIterator implements Iterator<String> {
item = null;
}
protected abstract void removeFromRedisStorage(String item);
protected abstract void removeFromRedisStorage(E item);
}

View File

@@ -20,13 +20,13 @@ import java.util.Queue;
/**
* Redis extension for the {@link List} contract. Supports {@link List} specific
* operations backed by Redis commands.
* operations backed by Redis operations.
*
* @author Costin Leau
*/
public interface RedisList extends RedisStore, List<String>, Queue<String> {
public interface RedisList<E> extends RedisStore<String>, List<E>, Queue<E> {
List<String> range(int start, int end);
List<E> range(int start, int end);
RedisList trim(int start, int end);
RedisList<E> trim(int start, int end);
}

View File

@@ -22,9 +22,9 @@ import java.util.Map;
*
* @author Costin Leau
*/
public interface RedisMap extends RedisStore, Map<String, String> {
public interface RedisMap<K, V> extends RedisStore<String>, Map<K, V> {
boolean putIfAbsent(String key, String value);
Integer increment(String key, int delta);
boolean putIfAbsent(K key, V value);
Integer increment(K key, int delta);
}

View File

@@ -1,39 +1,39 @@
/*
* Copyright 2010 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.datastore.redis.util;
import java.util.Set;
/**
* Redis extension for the {@link Set} contract. Supports {@link Set} specific
* operations backed by Redis commands.
*
* @author Costin Leau
*/
public interface RedisSet extends RedisStore, Set<String> {
Set<String> intersect(RedisSet... sets);
Set<String> union(RedisSet... sets);
Set<String> diff(RedisSet... sets);
RedisSet intersectAndStore(String destKey, RedisSet... sets);
RedisSet unionAndStore(String destKey, RedisSet... sets);
RedisSet diffAndStore(String destKey, RedisSet... sets);
}
/*
* Copyright 2010 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.datastore.redis.util;
import java.util.Set;
/**
* Redis extension for the {@link Set} contract. Supports {@link Set} specific
* operations backed by Redis operations.
*
* @author Costin Leau
*/
public interface RedisSet<E> extends RedisStore<String>, Set<E> {
Set<E> intersect(RedisSet<? extends E>... sets);
Set<E> union(RedisSet<? extends E>... sets);
Set<E> diff(RedisSet<? extends E>... sets);
RedisSet<E> intersectAndStore(String destKey, RedisSet<? extends E>... sets);
RedisSet<E> unionAndStore(String destKey, RedisSet<? extends E>... sets);
RedisSet<E> diffAndStore(String destKey, RedisSet<? extends E>... sets);
}

View File

@@ -20,21 +20,21 @@ import java.util.SortedSet;
/**
* Redis extension for the {@link SortedSet} contract. Supports {@link SortedSet} specific
* operations backed by Redis commands.
* operations backed by Redis operations.
*
* @author Costin Leau
*/
public interface RedisSortedSet extends RedisStore, SortedSet<String> {
public interface RedisSortedSet<E> extends RedisStore<String>, SortedSet<E> {
RedisSortedSet intersectAndStore(String destKey, RedisSortedSet... sets);
RedisSortedSet<E> intersectAndStore(String destKey, RedisSortedSet<E>... sets);
RedisSortedSet unionAndStore(String destKey, RedisSortedSet... sets);
RedisSortedSet<E> unionAndStore(String destKey, RedisSortedSet<E>... sets);
Set<String> range(int start, int end);
Set<E> range(int start, int end);
Set<String> rangeByScore(double min, double max);
Set<E> rangeByScore(double min, double max);
RedisSortedSet remove(int start, int end);
RedisSortedSet<E> remove(int start, int end);
RedisSortedSet removeByScore(double min, double max);
RedisSortedSet<E> removeByScore(double min, double max);
}

View File

@@ -15,18 +15,27 @@
*/
package org.springframework.datastore.redis.util;
import org.springframework.datastore.redis.core.RedisOperations;
/**
* Basic interface for Redis-based collections.
*
* @author Costin Leau
*/
public interface RedisStore {
public interface RedisStore<K> {
/**
* Returns the key used by the backing Redis store for this collection.
*
* @return Redis key
*/
String getKey();
K getKey();
/**
* Returns the underlying Redis operations used by the backing implementation.
*
* @return operations
*/
RedisOperations<K, ?> getOperations();
}

View File

@@ -0,0 +1,77 @@
/*
* Copyright 2010 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.datastore.redis;
import java.io.Serializable;
/**
* Simple serializable class.
*
* @author Costin Leau
*/
public class Address implements Serializable {
private static final long serialVersionUID = 4924045450477798779L;
private String street;
private Integer number;
/**
* Constructs a new <code>Address</code> instance.
*
* @param street
* @param number
*/
public Address(String street, int number) {
super();
this.street = street;
this.number = number;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((number == null) ? 0 : number.hashCode());
result = prime * result + ((street == null) ? 0 : street.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (!(obj instanceof Address))
return false;
Address other = (Address) obj;
if (number == null) {
if (other.number != null)
return false;
}
else if (!number.equals(other.number))
return false;
if (street == null) {
if (other.street != null)
return false;
}
else if (!street.equals(other.street))
return false;
return true;
}
}

View File

@@ -13,17 +13,40 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.datastore.redis.core;
package org.springframework.datastore.redis;
import java.io.Serializable;
/**
* Simple serializable class.
*
* @author Mark Pollack
* @author Costin Leau
*/
public class Person implements Serializable {
private static final long serialVersionUID = 92633004015631981L;
private String firstName;
private String lastName;
private int age;
private Integer age;
private Address address;
public Person() {
}
public Person(String firstName, String lastName, int age) {
this(firstName, lastName, age, null);
}
public Person(String firstName, String lastName, int age, Address address) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
this.address = address;
}
public String getFirstName() {
return firstName;
@@ -49,22 +72,22 @@ public class Person implements Serializable {
this.age = age;
}
public Person(String firstName, String lastName, int age) {
super();
this.firstName = firstName;
this.lastName = lastName;
this.age = age;
public Address getAddress() {
return address;
}
public void setAddress(Address address) {
this.address = address;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + age;
result = prime * result
+ ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result
+ ((lastName == null) ? 0 : lastName.hashCode());
result = prime * result + ((address == null) ? 0 : address.hashCode());
result = prime * result + ((age == null) ? 0 : age.hashCode());
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@@ -74,22 +97,33 @@ public class Person implements Serializable {
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
if (!(obj instanceof Person))
return false;
Person other = (Person) obj;
if (age != other.age)
if (address == null) {
if (other.address != null)
return false;
}
else if (!address.equals(other.address))
return false;
if (age == null) {
if (other.age != null)
return false;
}
else if (!age.equals(other.age))
return false;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
}
else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
}
else if (!lastName.equals(other.lastName))
return false;
return true;
}
}
}

View File

@@ -16,15 +16,13 @@
package org.springframework.datastore.redis.connection;
import static org.junit.Assert.assertEquals;
import junit.framework.Assert;
import static org.junit.Assert.*;
import static org.junit.Assume.*;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.datastore.redis.connection.RedisConnection;
import org.springframework.datastore.redis.connection.RedisConnectionFactory;
import org.springframework.datastore.redis.core.Person;
import org.springframework.datastore.redis.Person;
public abstract class AbstractConnectionIntegrationTests {
@@ -46,20 +44,24 @@ public abstract class AbstractConnectionIntegrationTests {
@Test
public void testLPush() throws Exception {
Integer index = connection.lPush(listName, "bar");
Integer index = connection.lPush(listName.getBytes(), "bar".getBytes());
if (index != null) {
assertEquals((Integer) (index + 1), connection.lPush(listName, "bar"));
assertEquals((Integer) (index + 1), connection.lPush(listName.getBytes(), "bar".getBytes()));
}
}
@Test
public void testSetAndGet() {
connection.set("foo", "blah blah");
String value = connection.get("foo");
Assert.assertEquals("blah blah", value);
assumeTrue(!isJredis());
connection.set("foo".getBytes(), "blahblah".getBytes());
assertEquals("blahblah", new String(connection.get("foo".getBytes())));
}
private boolean isJredis() {
return connection.getClass().getSimpleName().startsWith("Jredis");
}
public void conversions() {
Person p = new Person("Joe", "Trader", 33);
}

View File

@@ -18,6 +18,7 @@ package org.springframework.datastore.redis.core;
import org.junit.Before;
import org.junit.Test;
import org.springframework.datastore.redis.Person;
public class RedisTemplateIntegrationTests {

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2010 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.datastore.redis.serializer;
import static org.junit.Assert.*;
import java.io.Serializable;
import java.util.UUID;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.springframework.datastore.redis.Address;
import org.springframework.datastore.redis.Person;
public class SimpleRedisSerializerTests {
private static class A implements Serializable {
private Integer value = Integer.valueOf(30);
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
A other = (A) obj;
if (value == null) {
if (other.value != null)
return false;
}
else if (!value.equals(other.value))
return false;
return true;
}
}
private static class B implements Serializable {
private String name = getClass().getName();
private A a = new A();
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((a == null) ? 0 : a.hashCode());
result = prime * result + ((name == null) ? 0 : name.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
B other = (B) obj;
if (a == null) {
if (other.a != null)
return false;
}
else if (!a.equals(other.a))
return false;
if (name == null) {
if (other.name != null)
return false;
}
else if (!name.equals(other.name))
return false;
return true;
}
}
private RedisSerializer serializer;
@Before
public void setUp() {
serializer = new SimpleRedisSerializer();
}
@After
public void tearDown() {
serializer = null;
}
@Test
public void testBasicSerializationRoundtrip() throws Exception {
Integer integer = new Integer(300);
verifySerializedObjects(new Integer(300), new Double(200), new B());
}
private void verifySerializedObjects(Object... objects) {
for (Object object : objects) {
assertEquals("Incorrectly (de)serialized object " + object, object,
serializer.deserialize(serializer.serialize(object)));
}
}
@Test
public void testStringEncodedSerialization() {
String value = UUID.randomUUID().toString();
assertEquals(value, serializer.deserialize(serializer.serialize(value)));
assertEquals(value, serializer.deserialize(serializer.serialize(value)));
assertEquals(value, serializer.deserialize(serializer.serialize(value)));
}
@Test
public void testPersonSerialization() throws Exception {
String value = UUID.randomUUID().toString();
Person p1 = new Person(value, value, 1, new Address(value, 2));
assertEquals(p1, serializer.deserialize(serializer.serialize(p1)));
assertEquals(p1, serializer.deserialize(serializer.serialize(p1)));
}
}

View File

@@ -0,0 +1,265 @@
/*
* Copyright 2010 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.datastore.redis.util;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertThat;
import static org.junit.Assert.assertTrue;
import static org.junit.matchers.JUnitMatchers.hasItem;
import static org.junit.matchers.JUnitMatchers.hasItems;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
/**
* Base test for Redis collections.
*
* @author Costin Leau
*/
public abstract class AbstractRedisCollectionTests<T> {
protected AbstractRedisCollection<T> collection;
@Before
public void setUp() throws Exception {
collection = createCollection();
}
abstract AbstractRedisCollection<T> createCollection();
abstract void destroyCollection();
abstract RedisStore<T> copyStore(RedisStore<T> store);
/**
* Return a new instance of T
* @return
*/
abstract T getT();
@After
public void tearDown() throws Exception {
// remove the collection entirely since clear() doesn't always work
collection.getOperations().delete(collection.getKey());
destroyCollection();
}
@Test
public void testAdd() {
T t1 = getT();
assertThat(collection.add(t1), is(true));
assertThat(collection, hasItem(t1));
assertEquals(1, collection.size());
}
@SuppressWarnings("unchecked")
@Test
public void testAddAll() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
List<T> list = Arrays.asList(t1, t2, t3);
assertThat(collection.addAll(list), is(true));
assertThat(collection, hasItem(t1));
assertThat(collection, hasItem(t2));
assertThat(collection, hasItem(t3));
assertEquals(collection.size(), 3);
}
@Test
public void testClear() {
T t1 = getT();
assertEquals(0, collection.size());
collection.add(t1);
assertEquals(1, collection.size());
collection.clear();
assertEquals(0, collection.size());
}
@Test
public void containsObject() {
T t1 = getT();
assertThat(collection, not(hasItem(t1)));
assertThat(collection.add(t1), is(true));
assertThat(collection, hasItem(t1));
}
@SuppressWarnings("unchecked")
@Test
public void containsAll() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
List<T> list = Arrays.asList(t1, t2, t3);
assertThat(collection.addAll(list), is(true));
assertThat(collection.containsAll(list), is(true));
assertThat(collection, hasItems(t1, t2, t3));
}
@Test
public void testEquals() {
//assertEquals(collection, copyStore(collection));
}
@Test
public void testHashCode() {
assertThat(collection.hashCode(), not(equalTo(collection.getKey().hashCode())));
}
@Test
public void testIsEmpty() {
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
collection.add(getT());
assertEquals(1, collection.size());
assertFalse(collection.isEmpty());
collection.clear();
assertTrue(collection.isEmpty());
}
@Test
public void testIterator() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
List<T> list = Arrays.asList(t1, t2, t3);
assertThat(collection.addAll(list), is(true));
Iterator<T> iterator = collection.iterator();
assertEquals(t1, iterator.next());
assertEquals(t2, iterator.next());
assertEquals(t3, iterator.next());
assertFalse(iterator.hasNext());
}
@Test
public void testRemoveObject() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
assertEquals(0, collection.size());
assertThat(collection.add(t1), is(true));
assertThat(collection.add(t2), is(true));
assertEquals(2, collection.size());
assertThat(collection.remove(t3), is(false));
assertThat(collection.remove(t2), is(true));
assertThat(collection.remove(t2), is(false));
assertEquals(1, collection.size());
assertThat(collection.remove(t1), is(true));
assertEquals(0, collection.size());
}
@Test
public void removeAll() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
List<T> list = Arrays.asList(t1, t2, t3);
assertThat(collection.addAll(list), is(true));
assertThat(collection.containsAll(list), is(true));
assertThat(collection, hasItems(t1, t2, t3));
List<T> newList = Arrays.asList(getT(), getT());
List<T> partialList = Arrays.asList(getT(), t1, getT());
assertThat(collection.removeAll(newList), is(false));
assertThat(collection.removeAll(partialList), is(true));
assertThat(collection, not(hasItem(t1)));
assertThat(collection, hasItems(t2, t3));
assertThat(collection.removeAll(list), is(true));
assertThat(collection, not(hasItems(t2, t3)));
}
@Test(expected = UnsupportedOperationException.class)
public void testRetainAll() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
List<T> list = Arrays.asList(t1, t2);
List<T> newList = Arrays.asList(t2, t3);
assertThat(collection.addAll(list), is(true));
assertThat(collection, hasItems(t1, t2));
assertThat(collection.retainAll(newList), is(true));
assertThat(collection, not(hasItem(t1)));
assertThat(collection, hasItem(t2));
}
@Test
public void testSize() {
assertEquals(0, collection.size());
assertTrue(collection.isEmpty());
collection.add(getT());
assertEquals(1, collection.size());
collection.add(getT());
collection.add(getT());
assertEquals(3, collection.size());
}
@SuppressWarnings("unchecked")
@Test
public void testToArray() {
Object[] expectedArray = new Object[] { getT(), getT(), getT() };
List<T> list = (List<T>) Arrays.asList(expectedArray);
assertThat(collection.addAll(list), is(true));
Object[] array = collection.toArray();
assertArrayEquals(expectedArray, array);
}
@SuppressWarnings("unchecked")
@Test
public void testToArrayWithGenerics() {
Object[] expectedArray = new Object[] { getT(), getT(), getT() };
List<T> list = (List<T>) Arrays.asList(expectedArray);
assertThat(collection.addAll(list), is(true));
Object[] array = collection.toArray(new Object[expectedArray.length]);
assertArrayEquals(expectedArray, array);
}
@Test
public void testToString() {
String name = collection.toString();
collection.add(getT());
assertEquals(name, collection.toString());
}
}

View File

@@ -0,0 +1,260 @@
/*
* Copyright 2010 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.datastore.redis.util;
import static org.junit.Assert.*;
import java.util.Arrays;
import java.util.List;
import java.util.NoSuchElementException;
import org.junit.Before;
import org.junit.Test;
/**
* Integration test for RedisList
*
* @author Costin Leau
*/
public abstract class AbstractRedisListTests<T> extends AbstractRedisCollectionTests<T> {
protected RedisList<T> list;
@SuppressWarnings("unchecked")
@Before
public void setUp() throws Exception {
super.setUp();
list = (RedisList<T>) collection;
}
@Test
public void testAddIndexObjectHead() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
list.add(t1);
list.add(t2);
assertEquals(t1, list.get(0));
list.add(0, t3);
assertEquals(t3, list.get(0));
}
@Test
public void testAddIndexObjectTail() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
list.add(t1);
list.add(t2);
assertEquals(t2, list.get(1));
list.add(2, t3);
assertEquals(t3, list.get(2));
}
@Test(expected = IllegalArgumentException.class)
public void testAddIndexObjectMiddle() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
list.add(t1);
list.add(t2);
assertEquals(t1, list.get(0));
list.add(1, t3);
}
@Test
public void addAllIndexCollectionHead() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
T t4 = getT();
list.add(t1);
list.add(t2);
List<T> asList = Arrays.asList(t3, t4);
assertEquals(t1, list.get(0));
list.addAll(0, asList);
// verify insertion order
assertEquals(t3, list.get(0));
assertEquals(t4, list.get(1));
}
@Test
public void addAllIndexCollectionTail() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
T t4 = getT();
list.add(t1);
list.add(t2);
List<T> asList = Arrays.asList(t3, t4);
assertEquals(t1, list.get(0));
assertTrue(list.addAll(2, asList));
// verify insertion order
assertEquals(t3, list.get(2));
assertEquals(t4, list.get(3));
}
@Test(expected = IllegalArgumentException.class)
public void addAllIndexCollectionMiddle() {
T t1 = getT();
T t2 = getT();
T t3 = getT();
T t4 = getT();
list.add(t1);
list.add(t2);
List<T> asList = Arrays.asList(t3, t4);
assertEquals(t1, list.get(0));
assertTrue(list.addAll(1, asList));
}
@Test(expected = UnsupportedOperationException.class)
public void testIndexOfObject() {
T t1 = getT();
T t2 = getT();
assertEquals(-1, list.indexOf(t1));
list.add(t1);
assertEquals(0, list.indexOf(t1));
assertEquals(-1, list.indexOf(t2));
list.add(t2);
assertEquals(1, list.indexOf(t1));
}
@Test
public void testOffer() {
T t1 = getT();
assertTrue(list.offer(t1));
assertTrue(list.contains(t1));
}
@Test
public void testPeek() {
assertNull(list.peek());
T t1 = getT();
list.add(t1);
assertEquals(t1, list.peek());
list.clear();
assertNull(list.peek());
}
@Test
public void testElement() {
try {
list.element();
fail();
} catch (NoSuchElementException nse) {
// expected
}
T t1 = getT();
list.add(t1);
assertEquals(t1, list.element());
list.clear();
try {
list.element();
fail();
} catch (NoSuchElementException nse) {
// expected
}
}
@Test
public void testPoll() {
assertNull(list.poll());
T t1 = getT();
list.add(t1);
assertEquals(t1, list.poll());
assertNull(list.poll());
}
@Test
public void testRemove() {
try {
list.remove();
fail();
} catch (NoSuchElementException nse) {
// expected
}
T t1 = getT();
list.add(t1);
assertEquals(t1, list.remove());
try {
list.remove();
fail();
} catch (NoSuchElementException nse) {
// expected
}
}
@Test
public void testRange() {
T t1 = getT();
T t2 = getT();
assertTrue(list.range(0, -1).isEmpty());
list.add(t1);
list.add(t2);
assertEquals(2, list.range(0, -1).size());
assertEquals(t1, list.range(0, 0).get(0));
assertEquals(t2, list.range(1, 1).get(0));
}
@Test(expected = UnsupportedOperationException.class)
public void testRemoveIndex() {
T t1 = getT();
T t2 = getT();
assertNull(list.remove(0));
list.add(t1);
list.add(t2);
assertNull(list.remove(2));
assertEquals(t2, list.remove(1));
assertEquals(t1, list.remove(0));
}
@Test
public void testTrim() {
T t1 = getT();
T t2 = getT();
assertTrue(list.trim(0, 0).isEmpty());
list.add(t1);
list.add(t2);
assertEquals(2, list.size());
assertEquals(1, list.trim(0, 0).size());
assertEquals(1, list.size());
assertEquals(t1, list.get(0));
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2010 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.datastore.redis.util;
import java.util.UUID;
import org.springframework.datastore.redis.Address;
import org.springframework.datastore.redis.Person;
import org.springframework.datastore.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.datastore.redis.core.RedisTemplate;
/**
* Person-based Redis List test.
*
* @author Costin Leau
*/
public class PersonRedisListTests extends AbstractRedisListTests<Person> {
private JedisConnectionFactory factory;
private int counter = 0;
@Override
AbstractRedisCollection<Person> createCollection() {
String redisName = getClass().getName();
factory = new JedisConnectionFactory();
factory.setPooling(false);
factory.afterPropertiesSet();
RedisTemplate<String, Person> template = new RedisTemplate<String, Person>(factory);
return new DefaultRedisList<Person>(redisName, template);
}
@Override
void destroyCollection() {
factory.destroy();
}
@Override
RedisStore<Person> copyStore(RedisStore<Person> store) {
//return new DefaultRedisList<Person>(store.getKey(), (RedisOperations<String, Person>) store.getOperations());
return null;
}
@Override
Person getT() {
String uuid = UUID.randomUUID().toString();
return new Person(uuid, uuid, ++counter, new Address(uuid, counter));
}
}

View File

@@ -0,0 +1,60 @@
/*
* Copyright 2010 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.datastore.redis.util;
import java.util.UUID;
import org.springframework.datastore.redis.connection.jedis.JedisConnectionFactory;
import org.springframework.datastore.redis.core.RedisOperations;
import org.springframework.datastore.redis.core.RedisTemplate;
/**
* String-based Redis List test.
*
* @author Costin Leau
*/
public class StringRedisListTests extends AbstractRedisListTests<String> {
private JedisConnectionFactory factory;
@Override
AbstractRedisCollection<String> createCollection() {
String redisName = getClass().getName();
factory = new JedisConnectionFactory();
factory.setPooling(false);
factory.afterPropertiesSet();
RedisTemplate<String, String> template = new RedisTemplate<String, String>(factory);
return new DefaultRedisList<String>(redisName, template);
}
@Override
void destroyCollection() {
factory.destroy();
}
@Override
RedisStore<String> copyStore(RedisStore<String> store) {
return new DefaultRedisList<String>(store.getKey(), (RedisOperations<String, String>) store.getOperations());
}
@Override
String getT() {
return UUID.randomUUID().toString();
}
}