Allow usage of RedisTemplate without serialization

DATAREDIS-227

Add "enableDefaultSerializer" property on
RedisTemplate. If false, serializers can be null
and no serialization will be performed if they are.
This commit is contained in:
Jennifer Hickey
2013-07-30 18:31:27 -07:00
parent a5e8636247
commit c1cda95baa
6 changed files with 150 additions and 32 deletions

View File

@@ -91,7 +91,8 @@ class RedisCache implements Cache {
public ValueWrapper doInRedis(RedisConnection connection) throws DataAccessException {
waitForLock(connection);
byte[] bs = connection.get(computeKey(key));
return (bs == null ? null : new SimpleValueWrapper(template.getValueSerializer().deserialize(bs)));
Object value = template.getValueSerializer() != null ? template.getValueSerializer().deserialize(bs) : bs;
return (bs == null ? null : new SimpleValueWrapper(value));
}
}, true);
}
@@ -104,7 +105,13 @@ class RedisCache implements Cache {
public Object doInRedis(RedisConnection connection) throws DataAccessException {
waitForLock(connection);
connection.multi();
connection.set(k, template.getValueSerializer().serialize(value));
byte[] v;
if(template.getValueSerializer() == null && value instanceof byte[]) {
v = (byte[])value;
} else {
v = template.getValueSerializer().serialize(value);
}
connection.set(k, v);
connection.zAdd(setName, 0, k);
if (expiration > 0) {
@@ -171,6 +178,9 @@ class RedisCache implements Cache {
}
private byte[] computeKey(Object key) {
if(template.getKeySerializer() == null && key instanceof byte[]) {
return (byte[])key;
}
byte[] k = template.getKeySerializer().serialize(key);
if (prefix == null || prefix.length == 0)

View File

@@ -91,6 +91,9 @@ abstract class AbstractOperations<K, V> {
@SuppressWarnings("unchecked")
byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if(keySerializer() == null && key instanceof byte[]) {
return (byte[])key;
}
return keySerializer().serialize(key);
}
@@ -100,17 +103,26 @@ abstract class AbstractOperations<K, V> {
@SuppressWarnings("unchecked")
byte[] rawValue(Object value) {
if(valueSerializer() == null && value instanceof byte[]) {
return (byte[])value;
}
return valueSerializer().serialize(value);
}
@SuppressWarnings("unchecked")
<HK> byte[] rawHashKey(HK hashKey) {
Assert.notNull(hashKey, "non null hash key required");
if(hashKeySerializer() == null && hashKey instanceof byte[]) {
return (byte[])hashKey;
}
return hashKeySerializer().serialize(hashKey);
}
@SuppressWarnings("unchecked")
<HV> byte[] rawHashValue(HV value) {
if(hashValueSerializer() == null & value instanceof byte[]) {
return (byte[])value;
}
return hashValueSerializer().serialize(value);
}
@@ -145,6 +157,9 @@ abstract class AbstractOperations<K, V> {
@SuppressWarnings("unchecked")
Set<V> deserializeValues(Set<byte[]> rawValues) {
if(valueSerializer() == null) {
return (Set<V>)rawValues;
}
return SerializationUtils.deserialize(rawValues, valueSerializer());
}
@@ -155,23 +170,36 @@ abstract class AbstractOperations<K, V> {
}
Set<TypedTuple<V>> set = new LinkedHashSet<TypedTuple<V>>(rawValues.size());
for (Tuple rawValue : rawValues) {
set.add(new DefaultTypedTuple(valueSerializer().deserialize(rawValue.getValue()), rawValue.getScore()));
Object value = rawValue.getValue();
if(valueSerializer() != null) {
value = valueSerializer().deserialize(rawValue.getValue());
}
set.add(new DefaultTypedTuple(value, rawValue.getScore()));
}
return set;
}
@SuppressWarnings("unchecked")
List<V> deserializeValues(List<byte[]> rawValues) {
if(valueSerializer() == null) {
return (List<V>)rawValues;
}
return SerializationUtils.deserialize(rawValues, valueSerializer());
}
@SuppressWarnings("unchecked")
<T> Set<T> deserializeHashKeys(Set<byte[]> rawKeys) {
if(hashKeySerializer() == null) {
return (Set<T>)rawKeys;
}
return SerializationUtils.deserialize(rawKeys, hashKeySerializer());
}
@SuppressWarnings("unchecked")
<T> List<T> deserializeHashValues(List<byte[]> rawValues) {
if(hashValueSerializer() == null) {
return (List<T>)rawValues;
}
return SerializationUtils.deserialize(rawValues, hashValueSerializer());
}
@@ -193,11 +221,17 @@ abstract class AbstractOperations<K, V> {
@SuppressWarnings("unchecked")
K deserializeKey(byte[] value) {
if(keySerializer() == null) {
return (K) value;
}
return (K) keySerializer().deserialize(value);
}
@SuppressWarnings("unchecked")
V deserializeValue(byte[] value) {
if(valueSerializer() == null) {
return (V)value;
}
return (V) valueSerializer().deserialize(value);
}
@@ -207,11 +241,17 @@ abstract class AbstractOperations<K, V> {
@SuppressWarnings( { "unchecked" })
<HK> HK deserializeHashKey(byte[] value) {
if(hashKeySerializer() == null) {
return (HK)value;
}
return (HK) hashKeySerializer().deserialize(value);
}
@SuppressWarnings("unchecked")
<HV> HV deserializeHashValue(byte[] value) {
if(hashValueSerializer() == null) {
return (HV)value;
}
return (HV) hashValueSerializer().deserialize(value);
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.core;
import java.util.Arrays;
import org.springframework.data.redis.core.ZSetOperations.TypedTuple;
/**
@@ -76,7 +78,12 @@ class DefaultTypedTuple<V> implements TypedTuple<V> {
if (other.value != null)
return false;
}
else if (!value.equals(other.value))
else if(value instanceof byte[]) {
if(!(other.value instanceof byte[])) {
return false;
}
return Arrays.equals((byte[])value, (byte[])other.value);
} else if (!value.equals(other.value))
return false;
return true;
}

View File

@@ -74,6 +74,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
private boolean exposeConnection = false;
private boolean initialized = false;
private boolean enableDefaultSerializer = true;
private RedisSerializer<?> defaultSerializer = new JdkSerializationRedisSerializer();
private RedisSerializer keySerializer = null;
@@ -100,26 +101,26 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
super.afterPropertiesSet();
boolean defaultUsed = false;
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
if(enableDefaultSerializer) {
if (keySerializer == null) {
keySerializer = defaultSerializer;
defaultUsed = true;
}
if (valueSerializer == null) {
valueSerializer = defaultSerializer;
defaultUsed = true;
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
}
if (hashKeySerializer == null) {
hashKeySerializer = defaultSerializer;
defaultUsed = true;
}
if (hashValueSerializer == null) {
hashValueSerializer = defaultSerializer;
defaultUsed = true;
}
if (defaultUsed) {
if (enableDefaultSerializer && defaultUsed) {
Assert.notNull(defaultSerializer, "default serializer null and not all serializers initialized");
}
@@ -311,6 +312,24 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
this.exposeConnection = exposeConnection;
}
/**
*
* @return Whether or not the default serializer should be used. If not, any serializers not explicilty set
* will remain null and values will not be serialized or deserialized.
*/
public boolean isEnableDefaultSerializer() {
return enableDefaultSerializer;
}
/**
*
* @param enableDefaultSerializer Whether or not the default serializer should be used. If not,
* any serializers not explicilty set will remain null and values will not be serialized or deserialized.
*/
public void setEnableDefaultSerializer(boolean enableDefaultSerializer) {
this.enableDefaultSerializer = enableDefaultSerializer;
}
/**
* Returns the default serializer used by this template.
*
@@ -425,6 +444,9 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
@SuppressWarnings("unchecked")
private byte[] rawKey(Object key) {
Assert.notNull(key, "non null key required");
if(keySerializer == null && key instanceof byte[]) {
return (byte[]) key;
}
return keySerializer.serialize(key);
}
@@ -434,6 +456,9 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
@SuppressWarnings("unchecked")
private byte[] rawValue(Object value) {
if(valueSerializer == null && value instanceof byte[]) {
return (byte[]) value;
}
return valueSerializer.serialize(value);
}
@@ -450,7 +475,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
@SuppressWarnings("unchecked")
private K deserializeKey(byte[] value) {
return (K) keySerializer.deserialize(value);
return keySerializer != null ? (K) keySerializer.deserialize(value) : (K) value;
}
@SuppressWarnings({ "unchecked", "rawtypes" })
@@ -461,7 +486,7 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
List<Object> values = new ArrayList<Object>();
for(Object rawValue: rawValues) {
if(rawValue instanceof byte[]) {
if(rawValue instanceof byte[] && valueSerializer != null) {
values.add(valueSerializer.deserialize((byte[])rawValue));
} else if(rawValue instanceof List) {
// Lists are the only potential Collections of mixed values....
@@ -484,20 +509,24 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
return rawSet;
}
Object setValue = rawSet.iterator().next();
if(setValue instanceof byte[]) {
if(setValue instanceof byte[] && valueSerializer != null) {
return (SerializationUtils.deserialize((Set)rawSet, valueSerializer));
}else if(setValue instanceof Tuple) {
return deserializeTupleValues(rawSet, valueSerializer);
return convertTupleValues(rawSet, valueSerializer);
} else {
return rawSet;
}
}
@SuppressWarnings({ "unchecked", "rawtypes" })
private Set<TypedTuple<V>> deserializeTupleValues(Set<Tuple> rawValues, RedisSerializer valueSerializer) {
private Set<TypedTuple<V>> convertTupleValues(Set<Tuple> rawValues, RedisSerializer valueSerializer) {
Set<TypedTuple<V>> set = new LinkedHashSet<TypedTuple<V>>(rawValues.size());
for (Tuple rawValue : rawValues) {
set.add(new DefaultTypedTuple(valueSerializer.deserialize(rawValue.getValue()), rawValue.getScore()));
Object value = rawValue.getValue();
if(valueSerializer != null) {
value = valueSerializer.deserialize(rawValue.getValue());
}
set.add(new DefaultTypedTuple(value, rawValue.getScore()));
}
return set;
}
@@ -652,7 +681,8 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
}, true);
return SerializationUtils.deserialize(rawKeys, keySerializer);
return keySerializer != null ? SerializationUtils.deserialize(rawKeys, keySerializer) :
rawKeys;
}

View File

@@ -81,6 +81,7 @@ public abstract class SerializationUtils {
return ret;
}
@SuppressWarnings("unchecked")
public static <HK,HV> Map<HK, HV> deserialize(Map<byte[], byte[]> rawValues,
RedisSerializer<HK> hashKeySerializer, RedisSerializer<HV> hashValueSerializer) {
if (rawValues == null) {
@@ -88,8 +89,12 @@ public abstract class SerializationUtils {
}
Map<HK, HV> map = new LinkedHashMap<HK, HV>(rawValues.size());
for (Map.Entry<byte[], byte[]> entry : rawValues.entrySet()) {
map.put((HK) hashKeySerializer.deserialize(entry.getKey()),
(HV) hashValueSerializer.deserialize(entry.getValue()));
// May want to deserialize only key or value
HK key = hashKeySerializer != null ? (HK) hashKeySerializer.deserialize(entry.getKey()) :
(HK) entry.getKey();
HV value = hashValueSerializer != null ? (HV) hashValueSerializer.deserialize(entry.getValue()) :
(HV) entry.getValue();
map.put(key, value);
}
return map;
}