diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java index df5847189..fbbaff8c0 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java +++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueAdapter.java @@ -34,7 +34,6 @@ import org.springframework.context.ApplicationEventPublisher; import org.springframework.context.ApplicationListener; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.ConverterNotFoundException; -import org.springframework.dao.DataAccessException; import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter; import org.springframework.data.keyvalue.core.KeyValueAdapter; import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty; @@ -44,6 +43,7 @@ import org.springframework.data.redis.connection.MessageListener; import org.springframework.data.redis.connection.RedisConnection; import org.springframework.data.redis.core.PartialUpdate.PropertyUpdate; import org.springframework.data.redis.core.PartialUpdate.UpdateCommand; +import org.springframework.data.redis.core.RedisKeyValueAdapter.RedisUpdateObject.Index; import org.springframework.data.redis.core.convert.CustomConversions; import org.springframework.data.redis.core.convert.GeoIndexedPropertyValue; import org.springframework.data.redis.core.convert.KeyspaceConfiguration; @@ -61,6 +61,7 @@ import org.springframework.data.redis.listener.RedisMessageListenerContainer; import org.springframework.data.redis.util.ByteUtils; import org.springframework.data.util.CloseableIterator; import org.springframework.util.Assert; +import org.springframework.util.CollectionUtils; import org.springframework.util.ObjectUtils; /** @@ -198,9 +199,9 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#put(java.lang.Object, java.lang.Object, java.lang.String) */ @Override - public Object put(final Object id, final Object item, final String keyspace) { + public Object put(final Object id, Object item, String keyspace) { - final RedisData rdo = item instanceof RedisData ? (RedisData) item : new RedisData(); + RedisData rdo = item instanceof RedisData ? (RedisData) item : new RedisData(); if (!(item instanceof RedisData)) { converter.write(item, rdo); } @@ -208,7 +209,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter if (ObjectUtils.nullSafeEquals(EnableKeyspaceEvents.ON_DEMAND, enableKeyspaceEvents) && this.expirationListener.get() == null) { - if (rdo.getTimeToLive() != null && rdo.getTimeToLive().longValue() > 0) { + if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) { initKeyExpirationListener(); } } @@ -225,39 +226,35 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter } } - redisOps.execute(new RedisCallback() { + redisOps.execute((RedisCallback) connection -> { - @Override - public Object doInRedis(RedisConnection connection) throws DataAccessException { + byte[] key = toBytes(rdo.getId()); + byte[] objectKey = createKey(rdo.getKeyspace(), rdo.getId()); - byte[] key = toBytes(rdo.getId()); - byte[] objectKey = createKey(rdo.getKeyspace(), rdo.getId()); + boolean isNew = connection.del(objectKey) == 0; - boolean isNew = connection.del(objectKey) == 0; + connection.hMSet(objectKey, rdo.getBucket().rawMap()); - connection.hMSet(objectKey, rdo.getBucket().rawMap()); + if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) { - if (rdo.getTimeToLive() != null && rdo.getTimeToLive().longValue() > 0) { + connection.expire(objectKey, rdo.getTimeToLive()); - connection.expire(objectKey, rdo.getTimeToLive().longValue()); - - // add phantom key so values can be restored - byte[] phantomKey = ByteUtils.concat(objectKey, toBytes(":phantom")); - connection.del(phantomKey); - connection.hMSet(phantomKey, rdo.getBucket().rawMap()); - connection.expire(phantomKey, rdo.getTimeToLive().longValue() + 300); - } - - connection.sAdd(toBytes(rdo.getKeyspace()), key); - - IndexWriter indexWriter = new IndexWriter(connection, converter); - if (isNew) { - indexWriter.createIndexes(key, rdo.getIndexedData()); - } else { - indexWriter.deleteAndUpdateIndexes(key, rdo.getIndexedData()); - } - return null; + // add phantom key so values can be restored + byte[] phantomKey = ByteUtils.concat(objectKey, toBytes(":phantom")); + connection.del(phantomKey); + connection.hMSet(phantomKey, rdo.getBucket().rawMap()); + connection.expire(phantomKey, rdo.getTimeToLive() + 300); } + + connection.sAdd(toBytes(rdo.getKeyspace()), key); + + IndexWriter indexWriter = new IndexWriter(connection, converter); + if (isNew) { + indexWriter.createIndexes(key, rdo.getIndexedData()); + } else { + indexWriter.deleteAndUpdateIndexes(key, rdo.getIndexedData()); + } + return null; }); return item; @@ -268,17 +265,12 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#contains(java.lang.Object, java.lang.String) */ @Override - public boolean contains(final Object id, final String keyspace) { + public boolean contains(Object id, String keyspace) { - Boolean exists = redisOps.execute(new RedisCallback() { + Boolean exists = redisOps + .execute((RedisCallback) connection -> connection.sIsMember(toBytes(keyspace), toBytes(id))); - @Override - public Boolean doInRedis(RedisConnection connection) throws DataAccessException { - return connection.sIsMember(toBytes(keyspace), toBytes(id)); - } - }); - - return exists != null ? exists.booleanValue() : false; + return exists != null ? exists : false; } /* @@ -300,15 +292,10 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter String stringId = asString(id); String stringKeyspace = asString(keyspace); - final byte[] binId = createKey(stringKeyspace, stringId); + byte[] binId = createKey(stringKeyspace, stringId); - Map raw = redisOps.execute(new RedisCallback>() { - - @Override - public Map doInRedis(RedisConnection connection) throws DataAccessException { - return connection.hGetAll(binId); - } - }); + Map raw = redisOps + .execute((RedisCallback>) connection -> connection.hGetAll(binId)); RedisData data = new RedisData(raw); data.setId(stringId); @@ -322,7 +309,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#delete(java.lang.Object, java.lang.String) */ @Override - public Object delete(final Object id, final String keyspace) { + public Object delete(Object id, String keyspace) { return delete(id, keyspace, Object.class); } @@ -331,31 +318,27 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.AbstractKeyValueAdapter#delete(java.lang.Object, java.lang.String, java.lang.Class) */ @Override - public T delete(final Object id, final String keyspace, final Class type) { + public T delete(Object id, String keyspace, Class type) { - final byte[] binId = toBytes(id); - final byte[] binKeyspace = toBytes(keyspace); + byte[] binId = toBytes(id); + byte[] binKeyspace = toBytes(keyspace); T o = get(id, keyspace, type); if (o != null) { - final byte[] keyToDelete = createKey(asString(keyspace), asString(id)); + byte[] keyToDelete = createKey(asString(keyspace), asString(id)); - redisOps.execute(new RedisCallback() { + redisOps.execute((RedisCallback) connection -> { - @Override - public Void doInRedis(RedisConnection connection) throws DataAccessException { + connection.del(keyToDelete); + connection.sRem(binKeyspace, binId); - connection.del(keyToDelete); - connection.sRem(binKeyspace, binId); - - new IndexWriter(connection, converter).removeKeyFromIndexes(asString(keyspace), binId); - return null; - } + new IndexWriter(connection, converter).removeKeyFromIndexes(asString(keyspace), binId); + return null; }); - } + return o; } @@ -364,25 +347,18 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#getAllOf(java.lang.String) */ @Override - public List getAllOf(final String keyspace) { + public List getAllOf(String keyspace) { return getAllOf(keyspace, -1, -1); } - public List getAllOf(final String keyspace, long offset, int rows) { + public List getAllOf(String keyspace, long offset, int rows) { - final byte[] binKeyspace = toBytes(keyspace); + byte[] binKeyspace = toBytes(keyspace); - Set ids = redisOps.execute(new RedisCallback>() { + Set ids = redisOps.execute((RedisCallback>) connection -> connection.sMembers(binKeyspace)); - @Override - public Set doInRedis(RedisConnection connection) throws DataAccessException { - return connection.sMembers(binKeyspace); - } - }); - - List result = new ArrayList(); - - List keys = new ArrayList(ids); + List result = new ArrayList<>(); + List keys = new ArrayList<>(ids); if (keys.isEmpty() || keys.size() < offset) { return Collections.emptyList(); @@ -404,17 +380,13 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#deleteAllOf(java.lang.String) */ @Override - public void deleteAllOf(final String keyspace) { + public void deleteAllOf(String keyspace) { - redisOps.execute(new RedisCallback() { + redisOps.execute((RedisCallback) connection -> { - @Override - public Void doInRedis(RedisConnection connection) throws DataAccessException { - - connection.del(toBytes(keyspace)); - new IndexWriter(connection, converter).removeAllIndexes(asString(keyspace)); - return null; - } + connection.del(toBytes(keyspace)); + new IndexWriter(connection, converter).removeAllIndexes(asString(keyspace)); + return null; }); } @@ -432,95 +404,84 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @see org.springframework.data.keyvalue.core.KeyValueAdapter#count(java.lang.String) */ @Override - public long count(final String keyspace) { + public long count(String keyspace) { - Long count = redisOps.execute(new RedisCallback() { + Long count = redisOps.execute((RedisCallback) connection -> connection.sCard(toBytes(keyspace))); - @Override - public Long doInRedis(RedisConnection connection) throws DataAccessException { - return connection.sCard(toBytes(keyspace)); - } - }); - - return count != null ? count.longValue() : 0; + return count != null ? count : 0; } - public void update(final PartialUpdate update) { + public void update(PartialUpdate update) { - final RedisPersistentEntity entity = this.converter.getMappingContext() + RedisPersistentEntity entity = this.converter.getMappingContext() .getRequiredPersistentEntity(update.getTarget()); - final String keyspace = entity.getKeySpace(); - final Object id = update.getId(); + String keyspace = entity.getKeySpace(); + Object id = update.getId(); - final byte[] redisKey = createKey(keyspace, converter.getConversionService().convert(id, String.class)); + byte[] redisKey = createKey(keyspace, converter.getConversionService().convert(id, String.class)); - final RedisData rdo = new RedisData(); + RedisData rdo = new RedisData(); this.converter.write(update, rdo); - redisOps.execute(new RedisCallback() { + redisOps.execute((RedisCallback) connection -> { - @Override - public Void doInRedis(RedisConnection connection) throws DataAccessException { + RedisUpdateObject redisUpdateObject = new RedisUpdateObject(redisKey, keyspace, id); - RedisUpdateObject redisUpdateObject = new RedisUpdateObject(redisKey, keyspace, id); + for (PropertyUpdate pUpdate : update.getPropertyUpdates()) { - for (PropertyUpdate pUpdate : update.getPropertyUpdates()) { + String propertyPath = pUpdate.getPropertyPath(); - String propertyPath = pUpdate.getPropertyPath(); + if (UpdateCommand.DEL.equals(pUpdate.getCmd()) || pUpdate.getValue() instanceof Collection + || pUpdate.getValue() instanceof Map + || (pUpdate.getValue() != null && pUpdate.getValue().getClass().isArray()) || (pUpdate.getValue() != null + && !converter.getConversionService().canConvert(pUpdate.getValue().getClass(), byte[].class))) { - if (UpdateCommand.DEL.equals(pUpdate.getCmd()) || pUpdate.getValue() instanceof Collection - || pUpdate.getValue() instanceof Map - || (pUpdate.getValue() != null && pUpdate.getValue().getClass().isArray()) || (pUpdate.getValue() != null - && !converter.getConversionService().canConvert(pUpdate.getValue().getClass(), byte[].class))) { - - redisUpdateObject = fetchDeletePathsFromHashAndUpdateIndex(redisUpdateObject, propertyPath, connection); - } + redisUpdateObject = fetchDeletePathsFromHashAndUpdateIndex(redisUpdateObject, propertyPath, connection); } - - if (!redisUpdateObject.fieldsToRemove.isEmpty()) { - connection.hDel(redisKey, - redisUpdateObject.fieldsToRemove.toArray(new byte[redisUpdateObject.fieldsToRemove.size()][])); - } - - for (RedisUpdateObject.Index index : redisUpdateObject.indexesToUpdate) { - - if (ObjectUtils.nullSafeEquals(DataType.ZSET, index.type)) { - connection.zRem(index.key, toBytes(redisUpdateObject.targetId)); - } else { - connection.sRem(index.key, toBytes(redisUpdateObject.targetId)); - } - } - - if (!rdo.getBucket().isEmpty()) { - if (rdo.getBucket().size() > 1 - || (rdo.getBucket().size() == 1 && !rdo.getBucket().asMap().containsKey("_class"))) { - connection.hMSet(redisKey, rdo.getBucket().rawMap()); - } - } - - if (update.isRefreshTtl()) { - - if (rdo.getTimeToLive() != null && rdo.getTimeToLive().longValue() > 0) { - - connection.expire(redisKey, rdo.getTimeToLive().longValue()); - - // add phantom key so values can be restored - byte[] phantomKey = ByteUtils.concat(redisKey, toBytes(":phantom")); - connection.hMSet(phantomKey, rdo.getBucket().rawMap()); - connection.expire(phantomKey, rdo.getTimeToLive().longValue() + 300); - - } else { - - connection.persist(redisKey); - connection.persist(ByteUtils.concat(redisKey, toBytes(":phantom"))); - } - } - - new IndexWriter(connection, converter).updateIndexes(toBytes(id), rdo.getIndexedData()); - return null; } + if (!redisUpdateObject.fieldsToRemove.isEmpty()) { + connection.hDel(redisKey, + redisUpdateObject.fieldsToRemove.toArray(new byte[redisUpdateObject.fieldsToRemove.size()][])); + } + + for (Index index : redisUpdateObject.indexesToUpdate) { + + if (ObjectUtils.nullSafeEquals(DataType.ZSET, index.type)) { + connection.zRem(index.key, toBytes(redisUpdateObject.targetId)); + } else { + connection.sRem(index.key, toBytes(redisUpdateObject.targetId)); + } + } + + if (!rdo.getBucket().isEmpty()) { + if (rdo.getBucket().size() > 1 + || (rdo.getBucket().size() == 1 && !rdo.getBucket().asMap().containsKey("_class"))) { + connection.hMSet(redisKey, rdo.getBucket().rawMap()); + } + } + + if (update.isRefreshTtl()) { + + if (rdo.getTimeToLive() != null && rdo.getTimeToLive() > 0) { + + connection.expire(redisKey, rdo.getTimeToLive()); + + // add phantom key so values can be restored + byte[] phantomKey = ByteUtils.concat(redisKey, toBytes(":phantom")); + connection.hMSet(phantomKey, rdo.getBucket().rawMap()); + connection.expire(phantomKey, rdo.getTimeToLive() + 300); + + } else { + + connection.persist(redisKey); + connection.persist(ByteUtils.concat(redisKey, toBytes(":phantom"))); + } + } + + new IndexWriter(connection, converter).updateIndexes(toBytes(id), rdo.getIndexedData()); + return null; }); } @@ -532,8 +493,8 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter if (value != null && value.length > 0) { - byte[] existingValueIndexKey = value != null - ? ByteUtils.concatAll(toBytes(redisUpdateObject.keyspace), toBytes((":" + path)), toBytes(":"), value) : null; + byte[] existingValueIndexKey = ByteUtils.concatAll(toBytes(redisUpdateObject.keyspace), toBytes(":" + path), + toBytes(":"), value); if (connection.exists(existingValueIndexKey)) { redisUpdateObject.addIndexToUpdate(new RedisUpdateObject.Index(existingValueIndexKey, DataType.SET)); @@ -553,9 +514,8 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter if (value != null) { - byte[] existingValueIndexKey = value != null - ? ByteUtils.concatAll(toBytes(redisUpdateObject.keyspace), toBytes(":"), field, toBytes(":"), value) - : null; + byte[] existingValueIndexKey = ByteUtils.concatAll(toBytes(redisUpdateObject.keyspace), toBytes(":"), field, + toBytes(":"), value); if (connection.exists(existingValueIndexKey)) { redisUpdateObject.addIndexToUpdate(new RedisUpdateObject.Index(existingValueIndexKey, DataType.SET)); @@ -632,7 +592,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @return */ @SuppressWarnings({ "unchecked", "rawtypes" }) - private T readBackTimeToLiveIfSet(final byte[] key, T target) { + private T readBackTimeToLiveIfSet(byte[] key, T target) { if (target == null || key == null) { return target; @@ -778,7 +738,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @param ops * @param converter */ - public MappingExpirationListener(RedisMessageListenerContainer listenerContainer, RedisOperations ops, + MappingExpirationListener(RedisMessageListenerContainer listenerContainer, RedisOperations ops, RedisConverter converter) { super(listenerContainer); @@ -799,39 +759,32 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter byte[] key = message.getBody(); - final byte[] phantomKey = ByteUtils.concat(key, - converter.getConversionService().convert(":phantom", byte[].class)); + byte[] phantomKey = ByteUtils.concat(key, converter.getConversionService().convert(":phantom", byte[].class)); - Map hash = ops.execute(new RedisCallback>() { + Map hash = ops.execute((RedisCallback>) connection -> { - @Override - public Map doInRedis(RedisConnection connection) throws DataAccessException { + Map hash1 = connection.hGetAll(phantomKey); - Map hash = connection.hGetAll(phantomKey); - - if (!org.springframework.util.CollectionUtils.isEmpty(hash)) { - connection.del(phantomKey); - } - - return hash; + if (!CollectionUtils.isEmpty(hash1)) { + connection.del(phantomKey); } + + return hash1; }); Object value = converter.read(Object.class, new RedisData(hash)); String channel = !ObjectUtils.isEmpty(message.getChannel()) - ? converter.getConversionService().convert(message.getChannel(), String.class) : null; + ? converter.getConversionService().convert(message.getChannel(), String.class) + : null; - final RedisKeyExpiredEvent event = new RedisKeyExpiredEvent(channel, key, value); + RedisKeyExpiredEvent event = new RedisKeyExpiredEvent(channel, key, value); - ops.execute(new RedisCallback() { - @Override - public Void doInRedis(RedisConnection connection) throws DataAccessException { + ops.execute((RedisCallback) connection -> { - connection.sRem(converter.getConversionService().convert(event.getKeyspace(), byte[].class), event.getId()); - new IndexWriter(connection, converter).removeKeyFromIndexes(event.getKeyspace(), event.getId()); - return null; - } + connection.sRem(converter.getConversionService().convert(event.getKeyspace(), byte[].class), event.getId()); + new IndexWriter(connection, converter).removeKeyFromIndexes(event.getKeyspace(), event.getId()); + return null; }); publishEvent(event); @@ -844,11 +797,8 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter } byte[][] args = ByteUtils.split(message.getBody(), ':'); - if (args.length != 2) { - return false; - } - return true; + return args.length == 2; } } @@ -856,7 +806,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * @author Christoph Strobl * @since 1.8 */ - public static enum EnableKeyspaceEvents { + public enum EnableKeyspaceEvents { /** * Initializes the {@link KeyExpirationEventMessageListener} on startup. @@ -879,14 +829,14 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter * * @author Christoph Strobl */ - private static class RedisUpdateObject { + static class RedisUpdateObject { private final String keyspace; private final Object targetId; private final byte[] targetKey; - private Set fieldsToRemove = new LinkedHashSet(); - private Set indexesToUpdate = new LinkedHashSet(); + private Set fieldsToRemove = new LinkedHashSet<>(); + private Set indexesToUpdate = new LinkedHashSet<>(); RedisUpdateObject(byte[] targetKey, String keyspace, Object targetId) { diff --git a/src/main/java/org/springframework/data/redis/core/RedisKeyValueTemplate.java b/src/main/java/org/springframework/data/redis/core/RedisKeyValueTemplate.java index 1d65d4ff3..8824eb4bb 100644 --- a/src/main/java/org/springframework/data/redis/core/RedisKeyValueTemplate.java +++ b/src/main/java/org/springframework/data/redis/core/RedisKeyValueTemplate.java @@ -18,7 +18,6 @@ package org.springframework.data.redis.core; import java.util.ArrayList; import java.util.Collections; import java.util.List; -import java.util.Optional; import org.springframework.data.keyvalue.core.KeyValueAdapter; import org.springframework.data.keyvalue.core.KeyValueCallback; @@ -29,15 +28,16 @@ import org.springframework.util.ClassUtils; /** * Redis specific implementation of {@link KeyValueTemplate}. - * + * * @author Christoph Strobl + * @author Mark Paluch * @since 1.7 */ public class RedisKeyValueTemplate extends KeyValueTemplate { /** * Create new {@link RedisKeyValueTemplate}. - * + * * @param adapter must not be {@literal null}. * @param mappingContext must not be {@literal null}. */ @@ -58,7 +58,7 @@ public class RedisKeyValueTemplate extends KeyValueTemplate { * Retrieve entities by resolving their {@literal id}s and converting them into required type.
* The callback provides either a single {@literal id} or an {@link Iterable} of {@literal id}s, used for retrieving * the actual domain types and shortcuts manual retrieval and conversion of {@literal id}s via {@link RedisTemplate}. - * + * *
 	 * 
 	 * List<RedisSession> sessions = template.find(new RedisCallback<Set<byte[]>>() {
@@ -69,14 +69,14 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
 	 *   }
 	 * }, RedisSession.class);
 	 * 
-	 * 
+	 *
 	 * 
 	 *
 	 * @param callback provides the to retrieve entity ids. Must not be {@literal null}.
 	 * @param type must not be {@literal null}.
 	 * @return empty list if not elements found.
 	 */
-	public  List find(final RedisCallback callback, final Class type) {
+	public  List find(RedisCallback callback, Class type) {
 
 		Assert.notNull(callback, "Callback must not be null.");
 
@@ -92,18 +92,17 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
 				}
 
 				Iterable ids = ClassUtils.isAssignable(Iterable.class, callbackResult.getClass())
-						? (Iterable) callbackResult : Collections.singleton(callbackResult);
+						? (Iterable) callbackResult
+						: Collections.singleton(callbackResult);
 
 				List result = new ArrayList();
 				for (Object id : ids) {
 
 					String idToUse = adapter.getConverter().getConversionService().canConvert(id.getClass(), String.class)
-							? adapter.getConverter().getConversionService().convert(id, String.class) : id.toString();
+							? adapter.getConverter().getConversionService().convert(id, String.class)
+							: id.toString();
 
-					Optional candidate = findById(idToUse, type);
-					if (candidate.isPresent()) {
-						result.add(candidate.get());
-					}
+					findById(idToUse, type).ifPresent(result::add);
 				}
 
 				return result;
@@ -116,7 +115,7 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
 	 * @see org.springframework.data.keyvalue.core.KeyValueTemplate#insert(java.lang.Object, java.lang.Object)
 	 */
 	@Override
-	public void insert(final Object id, final Object objectToInsert) {
+	public void insert(Object id, Object objectToInsert) {
 
 		if (objectToInsert instanceof PartialUpdate) {
 			doPartialUpdate((PartialUpdate) objectToInsert);
@@ -156,7 +155,7 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
 
 	/**
 	 * Redis specific {@link KeyValueCallback}.
-	 * 
+	 *
 	 * @author Christoph Strobl
 	 * @param 
 	 * @since 1.7
diff --git a/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java b/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java
index 31a2bc07a..25f1d17c3 100644
--- a/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java
+++ b/src/main/java/org/springframework/data/redis/core/RedisQueryEngine.java
@@ -23,7 +23,6 @@ import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 
-import org.springframework.dao.DataAccessException;
 import org.springframework.data.geo.Circle;
 import org.springframework.data.geo.GeoResult;
 import org.springframework.data.geo.GeoResults;
@@ -31,7 +30,6 @@ import org.springframework.data.keyvalue.core.CriteriaAccessor;
 import org.springframework.data.keyvalue.core.QueryEngine;
 import org.springframework.data.keyvalue.core.SortAccessor;
 import org.springframework.data.keyvalue.core.query.KeyValueQuery;
-import org.springframework.data.redis.connection.RedisConnection;
 import org.springframework.data.redis.connection.RedisGeoCommands.GeoLocation;
 import org.springframework.data.redis.core.convert.GeoIndexedPropertyValue;
 import org.springframework.data.redis.core.convert.RedisData;
@@ -53,7 +51,7 @@ class RedisQueryEngine extends QueryEngine criteriaAccessor,
+	private RedisQueryEngine(CriteriaAccessor criteriaAccessor,
 			SortAccessor> sortAccessor) {
 		super(criteriaAccessor, sortAccessor);
 	}
@@ -75,8 +73,8 @@ class RedisQueryEngine extends QueryEngine Collection execute(final RedisOperationChain criteria, final Comparator sort, final long offset,
-			final int rows, final String keyspace, Class type) {
+	public  Collection execute(RedisOperationChain criteria, Comparator sort, long offset, int rows,
+			String keyspace, Class type) {
 
 		if (criteria == null
 				|| (CollectionUtils.isEmpty(criteria.getOrSismember()) && CollectionUtils.isEmpty(criteria.getSismember()))
@@ -84,60 +82,55 @@ class RedisQueryEngine extends QueryEngine) getAdapter().getAllOf(keyspace, offset, rows);
 		}
 
-		RedisCallback>> callback = new RedisCallback>>() {
-
-			@Override
-			public Map> doInRedis(RedisConnection connection) throws DataAccessException {
-
-				List allKeys = new ArrayList();
-				if (!criteria.getSismember().isEmpty()) {
-					allKeys.addAll(connection.sInter(keys(keyspace + ":", criteria.getSismember())));
-				}
-
-				if (!criteria.getOrSismember().isEmpty()) {
-					allKeys.addAll(connection.sUnion(keys(keyspace + ":", criteria.getOrSismember())));
-				}
-
-				if (criteria.getNear() != null) {
-
-					GeoResults> x = connection.geoRadius(geoKey(keyspace + ":", criteria.getNear()),
-							new Circle(criteria.getNear().getPoint(), criteria.getNear().getDistance()));
-					for (GeoResult> y : x) {
-						allKeys.add(y.getContent().getName());
-					}
-				}
-
-				byte[] keyspaceBin = getAdapter().getConverter().getConversionService().convert(keyspace + ":", byte[].class);
-
-				final Map> rawData = new LinkedHashMap>();
-
-				if (allKeys.isEmpty() || allKeys.size() < offset) {
-					return Collections.emptyMap();
-				}
-
-				int offsetToUse = Math.max(0, (int) offset);
-				if (rows > 0) {
-					allKeys = allKeys.subList(Math.max(0, offsetToUse), Math.min(offsetToUse + rows, allKeys.size()));
-				}
-				for (byte[] id : allKeys) {
-
-					byte[] singleKey = ByteUtils.concat(keyspaceBin, id);
-					rawData.put(id, connection.hGetAll(singleKey));
-				}
-
-				return rawData;
+		RedisCallback>> callback = connection -> {
 
+			List allKeys = new ArrayList<>();
+			if (!criteria.getSismember().isEmpty()) {
+				allKeys.addAll(connection.sInter(keys(keyspace + ":", criteria.getSismember())));
 			}
+
+			if (!criteria.getOrSismember().isEmpty()) {
+				allKeys.addAll(connection.sUnion(keys(keyspace + ":", criteria.getOrSismember())));
+			}
+
+			if (criteria.getNear() != null) {
+
+				GeoResults> x = connection.geoRadius(geoKey(keyspace + ":", criteria.getNear()),
+						new Circle(criteria.getNear().getPoint(), criteria.getNear().getDistance()));
+				for (GeoResult> y : x) {
+					allKeys.add(y.getContent().getName());
+				}
+			}
+
+			byte[] keyspaceBin = getAdapter().getConverter().getConversionService().convert(keyspace + ":", byte[].class);
+
+			Map> rawData = new LinkedHashMap<>();
+
+			if (allKeys.isEmpty() || allKeys.size() < offset) {
+				return Collections.emptyMap();
+			}
+
+			int offsetToUse = Math.max(0, (int) offset);
+			if (rows > 0) {
+				allKeys = allKeys.subList(Math.max(0, offsetToUse), Math.min(offsetToUse + rows, allKeys.size()));
+			}
+			for (byte[] id : allKeys) {
+
+				byte[] singleKey = ByteUtils.concat(keyspaceBin, id);
+				rawData.put(id, connection.hGetAll(singleKey));
+			}
+
+			return rawData;
 		};
 
 		Map> raw = this.getAdapter().execute(callback);
 
-		List result = new ArrayList(raw.size());
+		List result = new ArrayList<>(raw.size());
 		for (Map.Entry> entry : raw.entrySet()) {
 
 			RedisData data = new RedisData(entry.getValue());
 			data.setId(getAdapter().getConverter().getConversionService().convert(entry.getKey(), String.class));
-			data.setKeyspace(keyspace.toString());
+			data.setKeyspace(keyspace);
 
 			T converted = this.getAdapter().getConverter().read(type, data);
 
@@ -153,8 +146,8 @@ class RedisQueryEngine extends QueryEngine execute(final RedisOperationChain criteria, Comparator sort, long offset, int rows,
-			final String keyspace) {
+	public Collection execute(RedisOperationChain criteria, Comparator sort, long offset, int rows,
+			String keyspace) {
 		return execute(criteria, sort, offset, rows, keyspace, Object.class);
 	}
 
@@ -163,26 +156,22 @@ class RedisQueryEngine extends QueryEngine() {
+		return this.getAdapter().execute(connection -> {
 
-			@Override
-			public Long doInRedis(RedisConnection connection) throws DataAccessException {
-
-				String key = keyspace + ":";
-				byte[][] keys = new byte[criteria.getSismember().size()][];
-				int i = 0;
-				for (Object o : criteria.getSismember()) {
-					keys[i] = getAdapter().getConverter().getConversionService().convert(key + o, byte[].class);
-				}
-
-				return (long) connection.sInter(keys).size();
+			String key = keyspace + ":";
+			byte[][] keys = new byte[criteria.getSismember().size()][];
+			int i = 0;
+			for (Object o : criteria.getSismember()) {
+				keys[i] = getAdapter().getConverter().getConversionService().convert(key + o, byte[].class);
 			}
+
+			return (long) connection.sInter(keys).size();
 		});
 	}
 
diff --git a/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolver.java b/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolver.java
index 1e29e08b3..cd6eccb12 100644
--- a/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolver.java
+++ b/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolver.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015 the original author or authors.
+ * Copyright 2015-2017 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.
@@ -15,15 +15,15 @@
  */
 package org.springframework.data.redis.core.convert;
 
-import java.io.Serializable;
 import java.util.Map;
 
 import org.springframework.data.annotation.Reference;
 
 /**
  * {@link ReferenceResolver} retrieves Objects marked with {@link Reference} from Redis.
- * 
+ *
  * @author Christoph Strobl
+ * @author Mark Paluch
  * @since 1.7
  */
 public interface ReferenceResolver {
@@ -33,5 +33,5 @@ public interface ReferenceResolver {
 	 * @param keyspace must not be {@literal null}.
 	 * @return {@literal null} if referenced object does not exist.
 	 */
-	Map resolveReference(Serializable id, String keyspace);
+	Map resolveReference(Object id, String keyspace);
 }
diff --git a/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolverImpl.java b/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolverImpl.java
index c5f48193d..2e03427b0 100644
--- a/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolverImpl.java
+++ b/src/main/java/org/springframework/data/redis/core/convert/ReferenceResolverImpl.java
@@ -15,11 +15,8 @@
  */
 package org.springframework.data.redis.core.convert;
 
-import java.io.Serializable;
 import java.util.Map;
 
-import org.springframework.dao.DataAccessException;
-import org.springframework.data.redis.connection.RedisConnection;
 import org.springframework.data.redis.core.RedisCallback;
 import org.springframework.data.redis.core.RedisKeyValueAdapter;
 import org.springframework.data.redis.core.RedisOperations;
@@ -28,8 +25,9 @@ import org.springframework.util.Assert;
 
 /**
  * {@link ReferenceResolver} using {@link RedisKeyValueAdapter} to read raw data.
- * 
+ *
  * @author Christoph Strobl
+ * @author Mark Paluch
  * @since 1.7
  */
 public class ReferenceResolverImpl implements ReferenceResolver {
@@ -50,19 +48,13 @@ public class ReferenceResolverImpl implements ReferenceResolver {
 
 	/*
 	 * (non-Javadoc)
-	 * @see org.springframework.data.redis.core.convert.ReferenceResolver#resolveReference(java.io.Serializable, java.io.Serializable, java.lang.Class)
+	 * @see org.springframework.data.redis.core.convert.ReferenceResolver#resolveReference(java.lang.Object, java.lang.String)
 	 */
 	@Override
-	public Map resolveReference(Serializable id, String keyspace) {
+	public Map resolveReference(Object id, String keyspace) {
 
-		final byte[] key = converter.convert(keyspace + ":" + id);
+		byte[] key = converter.convert(keyspace + ":" + id);
 
-		return redisOps.execute(new RedisCallback>() {
-
-			@Override
-			public Map doInRedis(RedisConnection connection) throws DataAccessException {
-				return connection.hGetAll(key);
-			}
-		});
+		return redisOps.execute((RedisCallback>) connection -> connection.hGetAll(key));
 	}
 }
diff --git a/src/main/java/org/springframework/data/redis/hash/ObjectHashMapper.java b/src/main/java/org/springframework/data/redis/hash/ObjectHashMapper.java
index faada1865..4cd2899c7 100644
--- a/src/main/java/org/springframework/data/redis/hash/ObjectHashMapper.java
+++ b/src/main/java/org/springframework/data/redis/hash/ObjectHashMapper.java
@@ -15,7 +15,6 @@
  */
 package org.springframework.data.redis.hash;
 
-import java.io.Serializable;
 import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
@@ -144,7 +143,7 @@ public class ObjectHashMapper implements HashMapper {
 	 * @return
 	 */
 	public  T fromHash(Map hash, Class type) {
-		return (T) fromHash(hash);
+		return type.cast(fromHash(hash));
 	}
 
 	/**
@@ -158,10 +157,10 @@ public class ObjectHashMapper implements HashMapper {
 
 		/*
 		 * (non-Javadoc)
-		 * @see org.springframework.data.redis.core.convert.ReferenceResolver#resolveReference(java.io.Serializable, java.lang.String)
+		 * @see org.springframework.data.redis.core.convert.ReferenceResolver#resolveReference(java.lang.Object, java.lang.String)
 		 */
 		@Override
-		public Map resolveReference(Serializable id, String keyspace) {
+		public Map resolveReference(Object id, String keyspace) {
 			return NO_REFERENCE;
 		}
 	}
diff --git a/src/main/java/org/springframework/data/redis/repository/support/RedisRepositoryFactoryBean.java b/src/main/java/org/springframework/data/redis/repository/support/RedisRepositoryFactoryBean.java
index 039e507da..b87f83e39 100644
--- a/src/main/java/org/springframework/data/redis/repository/support/RedisRepositoryFactoryBean.java
+++ b/src/main/java/org/springframework/data/redis/repository/support/RedisRepositoryFactoryBean.java
@@ -1,5 +1,5 @@
 /*
- * Copyright 2015-2016 the original author or authors.
+ * Copyright 2015-2017 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.
@@ -15,8 +15,6 @@
  */
 package org.springframework.data.redis.repository.support;
 
-import java.io.Serializable;
-
 import org.springframework.beans.factory.FactoryBean;
 import org.springframework.data.keyvalue.core.KeyValueOperations;
 import org.springframework.data.keyvalue.repository.support.KeyValueRepositoryFactoryBean;
@@ -27,20 +25,21 @@ import org.springframework.data.repository.query.parser.AbstractQueryCreator;
 /**
  * Adapter for Springs {@link FactoryBean} interface to allow easy setup of {@link RedisRepositoryFactory} via Spring
  * configuration.
- * 
+ *
  * @author Christoph Strobl
  * @author Oliver Gierke
+ * @author Mark Paluch
  * @param  The repository type.
  * @param  The repository domain type.
  * @param  The repository id type.
  * @since 1.7
  */
-public class RedisRepositoryFactoryBean, S, ID extends Serializable>
+public class RedisRepositoryFactoryBean, S, ID>
 		extends KeyValueRepositoryFactoryBean {
 
 	/**
 	 * Creates a new {@link RedisRepositoryFactoryBean} for the given repository interface.
-	 * 
+	 *
 	 * @param repositoryInterface must not be {@literal null}.
 	 */
 	public RedisRepositoryFactoryBean(Class repositoryInterface) {
diff --git a/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java b/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java
index e2657f656..887f94266 100644
--- a/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/core/convert/MappingRedisConverterUnitTests.java
@@ -90,7 +90,7 @@ public class MappingRedisConverterUnitTests {
 
 		rand.id = "1";
 
-		assertThat(write(rand).getId(), is((Serializable) "1"));
+		assertThat(write(rand).getId(), is("1"));
 	}
 
 	@Test // DATAREDIS-425
diff --git a/src/test/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntityUnitTests.java b/src/test/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntityUnitTests.java
index f6b5bb23e..2ab795ada 100644
--- a/src/test/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntityUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/core/mapping/BasicRedisPersistentEntityUnitTests.java
@@ -42,7 +42,7 @@ import org.springframework.data.util.TypeInformation;
  * @param 
  */
 @RunWith(MockitoJUnitRunner.class)
-public class BasicRedisPersistentEntityUnitTests {
+public class BasicRedisPersistentEntityUnitTests {
 
 	public @Rule ExpectedException expectedException = ExpectedException.none();
 
diff --git a/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java b/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java
index ae780b092..cd5d780af 100644
--- a/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java
+++ b/src/test/java/org/springframework/data/redis/repository/RedisRepositoryIntegrationTestBase.java
@@ -24,6 +24,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Optional;
 
+import lombok.Data;
 import org.hamcrest.core.IsNull;
 import org.junit.Before;
 import org.junit.Test;
@@ -401,8 +402,8 @@ public abstract class RedisRepositoryIntegrationTestBase {
 	}
 
 	@RedisHash("persons")
-	@SuppressWarnings("serial")
-	public static class Person implements Serializable {
+	@Data
+	public static class Person {
 
 		@Id String id;
 		@Indexed String firstname;
@@ -417,127 +418,14 @@ public abstract class RedisRepositoryIntegrationTestBase {
 			this.firstname = firstname;
 			this.lastname = lastname;
 		}
-
-		public City getCity() {
-			return city;
-		}
-
-		public void setCity(City city) {
-			this.city = city;
-		}
-
-		public String getId() {
-			return id;
-		}
-
-		public void setId(String id) {
-			this.id = id;
-		}
-
-		public String getFirstname() {
-			return firstname;
-		}
-
-		public void setFirstname(String firstname) {
-			this.firstname = firstname;
-		}
-
-		public void setLastname(String lastname) {
-			this.lastname = lastname;
-		}
-
-		public String getLastname() {
-			return lastname;
-		}
-
-		@Override
-		public String toString() {
-			return "Person [id=" + id + ", firstname=" + firstname + "]";
-		}
-
-		@Override
-		public int hashCode() {
-			final int prime = 31;
-			int result = 1;
-			result = prime * result + ((firstname == null) ? 0 : firstname.hashCode());
-			result = prime * result + ((id == null) ? 0 : id.hashCode());
-			return result;
-		}
-
-		@Override
-		public boolean equals(Object obj) {
-			if (this == obj) {
-				return true;
-			}
-			if (obj == null) {
-				return false;
-			}
-			if (!(obj instanceof Person)) {
-				return false;
-			}
-			Person other = (Person) obj;
-			if (firstname == null) {
-				if (other.firstname != null) {
-					return false;
-				}
-			} else if (!firstname.equals(other.firstname)) {
-				return false;
-			}
-			if (id == null) {
-				if (other.id != null) {
-					return false;
-				}
-			} else if (!id.equals(other.id)) {
-				return false;
-			}
-			return true;
-		}
-
 	}
 
+	@Data
 	public static class City {
 
 		@Id String id;
 		String name;
 
 		@GeoIndexed Point location;
-
-		@Override
-		public int hashCode() {
-			final int prime = 31;
-			int result = 1;
-			result = prime * result + ((id == null) ? 0 : id.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 (!(obj instanceof City)) {
-				return false;
-			}
-			City other = (City) obj;
-			if (id == null) {
-				if (other.id != null) {
-					return false;
-				}
-			} else if (!id.equals(other.id)) {
-				return false;
-			}
-			if (name == null) {
-				if (other.name != null) {
-					return false;
-				}
-			} else if (!name.equals(other.name)) {
-				return false;
-			}
-			return true;
-		}
 	}
 }
diff --git a/src/test/java/org/springframework/data/redis/repository/core/MappingRedisEntityInformationUnitTests.java b/src/test/java/org/springframework/data/redis/repository/core/MappingRedisEntityInformationUnitTests.java
index 314c86772..9077e20b8 100644
--- a/src/test/java/org/springframework/data/redis/repository/core/MappingRedisEntityInformationUnitTests.java
+++ b/src/test/java/org/springframework/data/redis/repository/core/MappingRedisEntityInformationUnitTests.java
@@ -32,7 +32,7 @@ import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
  * @author Mark Paluch
  */
 @RunWith(MockitoJUnitRunner.class)
-public class MappingRedisEntityInformationUnitTests {
+public class MappingRedisEntityInformationUnitTests {
 
 	@Mock RedisPersistentEntity entity;