From 5719947ee7b5cb8a0db76cb16d0c12b03438e47c Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Fri, 21 Jul 2017 15:31:12 +0200 Subject: [PATCH] DATAREDIS-664 - Polishing. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Remove Serializable ID constraints from factory beans. Replace casts with type.cast(…). Convert anonymous inner classes to lambdas. Remove unused code and casts. Simplify test entities by removing Serializable and using lombok. Formatting, Javadoc. Original pull request: #256. --- .../data/redis/core/RedisKeyValueAdapter.java | 330 ++++++++---------- .../redis/core/RedisKeyValueTemplate.java | 27 +- .../data/redis/core/RedisQueryEngine.java | 119 +++---- .../redis/core/convert/ReferenceResolver.java | 8 +- .../core/convert/ReferenceResolverImpl.java | 20 +- .../data/redis/hash/ObjectHashMapper.java | 7 +- .../support/RedisRepositoryFactoryBean.java | 11 +- .../MappingRedisConverterUnitTests.java | 2 +- .../BasicRedisPersistentEntityUnitTests.java | 2 +- .../RedisRepositoryIntegrationTestBase.java | 120 +------ ...appingRedisEntityInformationUnitTests.java | 2 +- 11 files changed, 232 insertions(+), 416 deletions(-) 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;