DATAREDIS-849 - Add support for immutable objects.

We now support immutable objects for saving (e.g. object without a provided Id) and loading (i.e. persistence constructor declares a subset of properties). New instances are created using wither methods/Kotlin copy(…) methods if an immutable object requires association with an Id.

Association of the Id to its object moved from RedisKeyValueAdapter to RedisKeyValueTemplate.
This commit is contained in:
Mark Paluch
2018-07-03 16:46:00 +02:00
committed by Oliver Gierke
parent 3defab118e
commit 322cfabb17
7 changed files with 140 additions and 21 deletions

View File

@@ -36,7 +36,7 @@ import org.springframework.core.convert.ConversionService;
import org.springframework.core.convert.ConverterNotFoundException;
import org.springframework.data.keyvalue.core.AbstractKeyValueAdapter;
import org.springframework.data.keyvalue.core.KeyValueAdapter;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.connection.MessageListener;
@@ -217,15 +217,7 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
}
if (rdo.getId() == null) {
rdo.setId(converter.getConversionService().convert(id, String.class));
if (!(item instanceof RedisData)) {
KeyValuePersistentProperty idProperty = converter.getMappingContext()
.getRequiredPersistentEntity(item.getClass()).getRequiredIdProperty();
converter.getMappingContext().getRequiredPersistentEntity(item.getClass()).getPropertyAccessor(item)
.setProperty(idProperty, id);
}
}
redisOps.execute((RedisCallback<Object>) connection -> {
@@ -624,8 +616,13 @@ public class RedisKeyValueAdapter extends AbstractKeyValueAdapter
});
if (timeout != null || !ttlProperty.getType().isPrimitive()) {
entity.getPropertyAccessor(target).setProperty(ttlProperty,
PersistentPropertyAccessor<T> propertyAccessor = entity.getPropertyAccessor(target);
propertyAccessor.setProperty(ttlProperty,
converter.getConversionService().convert(timeout, ttlProperty.getType()));
target = propertyAccessor.getBean();
}
}

View File

@@ -22,8 +22,12 @@ import java.util.List;
import org.springframework.data.keyvalue.core.KeyValueAdapter;
import org.springframework.data.keyvalue.core.KeyValueCallback;
import org.springframework.data.keyvalue.core.KeyValueTemplate;
import org.springframework.data.keyvalue.core.mapping.KeyValuePersistentProperty;
import org.springframework.data.mapping.PersistentPropertyAccessor;
import org.springframework.data.redis.core.convert.RedisConverter;
import org.springframework.data.redis.core.convert.RedisData;
import org.springframework.data.redis.core.mapping.RedisMappingContext;
import org.springframework.data.redis.core.mapping.RedisPersistentEntity;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
@@ -127,14 +131,31 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
* @see org.springframework.data.keyvalue.core.KeyValueTemplate#insert(java.lang.Object, java.lang.Object)
*/
@Override
public void insert(Object id, Object objectToInsert) {
public <T> T insert(Object id, T objectToInsert) {
if (objectToInsert instanceof PartialUpdate) {
doPartialUpdate((PartialUpdate<?>) objectToInsert);
return;
return objectToInsert;
}
super.insert(id, objectToInsert);
if (!(objectToInsert instanceof RedisData)) {
RedisConverter converter = adapter.getConverter();
RedisPersistentEntity<?> entity = converter.getMappingContext()
.getRequiredPersistentEntity(objectToInsert.getClass());
KeyValuePersistentProperty idProperty = entity.getRequiredIdProperty();
PersistentPropertyAccessor<T> propertyAccessor = entity.getPropertyAccessor(objectToInsert);
if (propertyAccessor.getProperty(idProperty) == null) {
propertyAccessor.setProperty(idProperty, id);
return super.insert(id, propertyAccessor.getBean());
}
}
return super.insert(id, objectToInsert);
}
/*
@@ -142,14 +163,20 @@ public class RedisKeyValueTemplate extends KeyValueTemplate {
* @see org.springframework.data.keyvalue.core.KeyValueTemplate#update(java.lang.Object)
*/
@Override
public void update(Object objectToUpdate) {
public <T> T update(T objectToUpdate) {
if (objectToUpdate instanceof PartialUpdate) {
doPartialUpdate((PartialUpdate<?>) objectToUpdate);
return;
return objectToUpdate;
}
super.update(objectToUpdate);
return super.update(objectToUpdate);
}
@Override
public <T> T update(Object id, T objectToUpdate) {
return super.update(id, objectToUpdate);
}
protected void doPartialUpdate(final PartialUpdate<?> update) {

View File

@@ -211,7 +211,11 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
R instance = (R) conversionService.convert(partial, readType.getType());
if (entity != null && entity.hasIdProperty()) {
entity.getPropertyAccessor(instance).setProperty(entity.getRequiredIdProperty(), source.getId());
PersistentPropertyAccessor<R> propertyAccessor = entity.getPropertyAccessor(instance);
propertyAccessor.setProperty(entity.getRequiredIdProperty(), source.getId());
instance = propertyAccessor.getBean();
}
return instance;
}
@@ -246,7 +250,7 @@ public class MappingRedisConverter implements RedisConverter, InitializingBean {
readAssociation(path, source, entity, accessor);
return (R) instance;
return (R) accessor.getBean();
}
@SuppressWarnings("unchecked")