DATACASS-227 - Moved to PersistenPropertyAccessor API.
Removed all references to BeanWrapper.create(…) and rather use the PersistentPropertyAccessor API instead. Related tickets: DATACMNS-738.
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors
|
||||
* Copyright 2013-2015 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,6 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import static org.springframework.data.cassandra.repository.support.BasicMapId.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
|
||||
@@ -32,9 +34,10 @@ import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
import org.springframework.data.cassandra.repository.MapIdentifiable;
|
||||
import org.springframework.data.convert.EntityInstantiator;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.mapping.model.SpELContext;
|
||||
@@ -49,8 +52,6 @@ import com.datastax.driver.core.querybuilder.Insert;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Update;
|
||||
|
||||
import static org.springframework.data.cassandra.repository.support.BasicMapId.id;
|
||||
|
||||
/**
|
||||
* {@link CassandraConverter} that uses a {@link MappingContext} to do sophisticated mapping of domain objects to
|
||||
* {@link Row}.
|
||||
@@ -59,8 +60,8 @@ import static org.springframework.data.cassandra.repository.support.BasicMapId.i
|
||||
* @author Matthew T. Adams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter implements CassandraConverter,
|
||||
ApplicationContextAware, BeanClassLoaderAware {
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter
|
||||
implements CassandraConverter, ApplicationContextAware, BeanClassLoaderAware {
|
||||
|
||||
protected final Logger log = LoggerFactory.getLogger(getClass());
|
||||
|
||||
@@ -123,7 +124,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
protected <S> S readEntityFromRow(final CassandraPersistentEntity<S> entity, final Row row) {
|
||||
|
||||
DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
|
||||
|
||||
BasicCassandraRowValueProvider rowValueProvider = new BasicCassandraRowValueProvider(row, evaluator);
|
||||
|
||||
CassandraPersistentEntityParameterValueProvider parameterProvider = new CassandraPersistentEntityParameterValueProvider(
|
||||
@@ -132,28 +132,26 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, parameterProvider);
|
||||
|
||||
BeanWrapper<S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
readPropertiesFromRow(entity, rowValueProvider, getConvertingAccessor(instance, entity));
|
||||
|
||||
readPropertiesFromRow(entity, rowValueProvider, wrapper);
|
||||
|
||||
return wrapper.getBean();
|
||||
return instance;
|
||||
}
|
||||
|
||||
protected void readPropertiesFromRow(final CassandraPersistentEntity<?> entity,
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?> wrapper) {
|
||||
final BasicCassandraRowValueProvider row, final PersistentPropertyAccessor accessor) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
MappingCassandraConverter.this.readPropertyFromRow(entity, prop, row, wrapper);
|
||||
MappingCassandraConverter.this.readPropertyFromRow(entity, prop, row, accessor);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
protected void readPropertyFromRow(final CassandraPersistentEntity<?> entity, final CassandraPersistentProperty prop,
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?> wrapper) {
|
||||
final BasicCassandraRowValueProvider row, final PersistentPropertyAccessor accessor) {
|
||||
|
||||
if (entity.isConstructorArgument(prop)) { // skip 'cause prop was set in ctor
|
||||
return;
|
||||
@@ -163,19 +161,19 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
|
||||
// get the key
|
||||
CassandraPersistentProperty keyProperty = entity.getIdProperty();
|
||||
Object key = wrapper.getProperty(keyProperty);
|
||||
CassandraPersistentEntity<?> keyEntity = keyProperty.getCompositePrimaryKeyEntity();
|
||||
|
||||
Object key = accessor.getProperty(keyProperty);
|
||||
|
||||
if (key == null) {
|
||||
key = instantiatePrimaryKey(keyProperty.getCompositePrimaryKeyEntity(), keyProperty, row);
|
||||
key = instantiatePrimaryKey(keyEntity, keyProperty, row);
|
||||
}
|
||||
|
||||
// wrap the key
|
||||
BeanWrapper<Object> keyWrapper = BeanWrapper.create(key, conversionService);
|
||||
|
||||
// now recurse on using the key this time
|
||||
readPropertiesFromRow(prop.getCompositePrimaryKeyEntity(), row, keyWrapper);
|
||||
readPropertiesFromRow(prop.getCompositePrimaryKeyEntity(), row, getConvertingAccessor(key, keyEntity));
|
||||
|
||||
// now that the key's properties have been populated, set the key property on the entity
|
||||
wrapper.setProperty(keyProperty, keyWrapper.getBean());
|
||||
accessor.setProperty(keyProperty, key);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -184,7 +182,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
Object obj = row.getPropertyValue(prop);
|
||||
wrapper.setProperty(prop, obj);
|
||||
accessor.setProperty(prop, obj);
|
||||
}
|
||||
|
||||
protected Object instantiatePrimaryKey(CassandraPersistentEntity<?> entity, CassandraPersistentProperty keyProperty,
|
||||
@@ -192,8 +190,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
|
||||
return instantiator.createInstance(entity, new CassandraPersistentEntityParameterValueProvider(entity,
|
||||
propertyProvider, null));
|
||||
return instantiator.createInstance(entity,
|
||||
new CassandraPersistentEntityParameterValueProvider(entity, propertyProvider, null));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -230,10 +228,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void writeInsertFromObject(final Object object, final Insert insert, CassandraPersistentEntity<?> entity) {
|
||||
writeInsertFromWrapper(BeanWrapper.create(object, conversionService), insert, entity);
|
||||
writeInsertFromWrapper(getConvertingAccessor(object, entity), insert, entity);
|
||||
}
|
||||
|
||||
protected void writeInsertFromWrapper(final BeanWrapper<Object> wrapper, final Insert insert,
|
||||
protected void writeInsertFromWrapper(final ConvertingPropertyAccessor accessor, final Insert insert,
|
||||
CassandraPersistentEntity<?> entity) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
@@ -241,14 +239,15 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
Object value = wrapper.getProperty(prop, prop.getType());
|
||||
Object value = accessor.getProperty(prop, prop.getType());
|
||||
|
||||
log.debug("prop.type -> " + prop.getType().getName());
|
||||
log.debug("prop.value -> " + value);
|
||||
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
log.debug("prop is a compositeKey");
|
||||
writeInsertFromWrapper(BeanWrapper.create(value, conversionService), insert,
|
||||
|
||||
writeInsertFromWrapper(getConvertingAccessor(value, prop.getCompositePrimaryKeyEntity()), insert,
|
||||
prop.getCompositePrimaryKeyEntity());
|
||||
return;
|
||||
}
|
||||
@@ -262,10 +261,10 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void writeUpdateFromObject(final Object object, final Update update, CassandraPersistentEntity<?> entity) {
|
||||
writeUpdateFromWrapper(BeanWrapper.create(object, conversionService), update, entity);
|
||||
writeUpdateFromWrapper(getConvertingAccessor(object, entity), update, entity);
|
||||
}
|
||||
|
||||
protected void writeUpdateFromWrapper(final BeanWrapper<Object> wrapper, final Update update,
|
||||
protected void writeUpdateFromWrapper(final ConvertingPropertyAccessor accessor, final Update update,
|
||||
final CassandraPersistentEntity<?> entity) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
@@ -273,11 +272,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
Object value = wrapper.getProperty(prop, prop.getType());
|
||||
Object value = accessor.getProperty(prop, prop.getType());
|
||||
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
writeUpdateFromWrapper(BeanWrapper.create(value, conversionService), update,
|
||||
prop.getCompositePrimaryKeyEntity());
|
||||
CassandraPersistentEntity<?> keyEntity = prop.getCompositePrimaryKeyEntity();
|
||||
writeUpdateFromWrapper(getConvertingAccessor(value, keyEntity), update, keyEntity);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -292,11 +291,12 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
});
|
||||
}
|
||||
|
||||
protected void writeDeleteWhereFromObject(final Object object, final Where where, CassandraPersistentEntity<?> entity) {
|
||||
writeDeleteWhereFromWrapper(BeanWrapper.create(object, conversionService), where, entity);
|
||||
protected void writeDeleteWhereFromObject(final Object object, final Where where,
|
||||
CassandraPersistentEntity<?> entity) {
|
||||
writeDeleteWhereFromWrapper(getConvertingAccessor(object, entity), where, entity);
|
||||
}
|
||||
|
||||
protected void writeDeleteWhereFromWrapper(final BeanWrapper<Object> wrapper, final Where where,
|
||||
protected void writeDeleteWhereFromWrapper(final PersistentPropertyAccessor accessor, final Where where,
|
||||
CassandraPersistentEntity<?> entity) {
|
||||
|
||||
// if the entity itself if a composite primary key, then we've recursed, so just add columns & return
|
||||
@@ -304,16 +304,16 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
where.and(QueryBuilder.eq(p.getColumnName().toCql(), wrapper.getProperty(p)));
|
||||
where.and(QueryBuilder.eq(p.getColumnName().toCql(), accessor.getProperty(p)));
|
||||
}
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// else, wrapper is an entity with an id
|
||||
Object id = getId(wrapper, entity);
|
||||
Object id = getId(accessor, entity);
|
||||
if (id == null) {
|
||||
String msg = String.format("no id value found in object {}", wrapper.getBean());
|
||||
String msg = String.format("no id value found in object {}", accessor.getBean());
|
||||
log.error(msg);
|
||||
throw new IllegalArgumentException(msg);
|
||||
}
|
||||
@@ -327,10 +327,14 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
CassandraPersistentProperty idProperty = entity.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
|
||||
if (idProperty.isCompositePrimaryKey()) {
|
||||
writeDeleteWhereFromWrapper(BeanWrapper.create(id, conversionService), where,
|
||||
|
||||
CassandraPersistentEntity<?> idEntity = idProperty.getCompositePrimaryKeyEntity();
|
||||
|
||||
writeDeleteWhereFromWrapper(getConvertingAccessor(id, idEntity), where,
|
||||
idProperty.getCompositePrimaryKeyEntity());
|
||||
return;
|
||||
}
|
||||
@@ -345,14 +349,13 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
|
||||
Assert.notNull(object);
|
||||
|
||||
final BeanWrapper<?> wrapper = object instanceof BeanWrapper ? (BeanWrapper<?>) object : BeanWrapper.create(object,
|
||||
conversionService);
|
||||
final ConvertingPropertyAccessor wrapper = getConvertingAccessor(object, entity);
|
||||
object = wrapper.getBean();
|
||||
|
||||
if (!entity.getType().isAssignableFrom(object.getClass())) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"given instance of type [%s] is not of compatible expected type [%s]", object.getClass().getName(), entity
|
||||
.getType().getName()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("given instance of type [%s] is not of compatible expected type [%s]",
|
||||
object.getClass().getName(), entity.getType().getName()));
|
||||
}
|
||||
|
||||
if (object instanceof MapIdentifiable) {
|
||||
@@ -400,4 +403,19 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
public CassandraMappingContext getMappingContext() {
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ConvertingPropertyAccessor} for the given source and entity.
|
||||
*
|
||||
* @param source must not be {@literal null}.
|
||||
* @param entity must not be {@literal null}.
|
||||
* @return
|
||||
*/
|
||||
private ConvertingPropertyAccessor getConvertingAccessor(Object source, CassandraPersistentEntity<?> entity) {
|
||||
|
||||
PersistentPropertyAccessor accessor = source instanceof PersistentPropertyAccessor
|
||||
? (PersistentPropertyAccessor) source : entity.getPropertyAccessor(source);
|
||||
|
||||
return new ConvertingPropertyAccessor(accessor, conversionService);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,9 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.cassandra.core.AsynchronousQueryListener;
|
||||
import org.springframework.cassandra.core.Cancellable;
|
||||
import org.springframework.cassandra.core.CqlOperations;
|
||||
import org.springframework.cassandra.core.CqlTemplate;
|
||||
import org.springframework.cassandra.core.Cancellable;
|
||||
import org.springframework.cassandra.core.QueryForObjectListener;
|
||||
import org.springframework.cassandra.core.QueryOptions;
|
||||
import org.springframework.cassandra.core.SessionCallback;
|
||||
@@ -39,16 +39,15 @@ import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.convert.EntityWriter;
|
||||
import org.springframework.data.mapping.PersistentPropertyAccessor;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.SimpleStatement;
|
||||
import com.datastax.driver.core.Statement;
|
||||
import com.datastax.driver.core.querybuilder.Batch;
|
||||
import com.datastax.driver.core.querybuilder.Clause;
|
||||
import com.datastax.driver.core.querybuilder.Delete;
|
||||
@@ -335,9 +334,9 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(type);
|
||||
|
||||
if (entity.getIdProperty().isCompositePrimaryKey()) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"entity class [%s] uses a composite primary key class [%s] which this method can't support", type.getName(),
|
||||
entity.getIdProperty().getCompositePrimaryKeyEntity().getType().getName()));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("entity class [%s] uses a composite primary key class [%s] which this method can't support",
|
||||
type.getName(), entity.getIdProperty().getCompositePrimaryKeyEntity().getType().getName()));
|
||||
}
|
||||
|
||||
Select select = QueryBuilder.select().all().from(entity.getTableName().toCql());
|
||||
@@ -390,16 +389,18 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
if (idProperty.isCompositePrimaryKey()) {
|
||||
|
||||
CassandraPersistentEntity<?> idEntity = idProperty.getCompositePrimaryKeyEntity();
|
||||
PersistentPropertyAccessor accessor = idEntity.getPropertyAccessor(id);
|
||||
|
||||
final BeanWrapper<Object> idWrapper = BeanWrapper.create(id, cassandraConverter.getConversionService());
|
||||
final ConvertingPropertyAccessor idAccessor = new ConvertingPropertyAccessor(accessor,
|
||||
cassandraConverter.getConversionService());
|
||||
|
||||
idEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
|
||||
clauseCallback.doWithClause(QueryBuilder.eq(p.getColumnName().toCql(),
|
||||
idWrapper.getProperty(p, p.getActualType())));
|
||||
clauseCallback
|
||||
.doWithClause(QueryBuilder.eq(p.getColumnName().toCql(), idAccessor.getProperty(p, p.getActualType())));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -1034,7 +1035,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
if (query instanceof Select) {
|
||||
return queryAsynchronously((Select) query, aql);
|
||||
}
|
||||
throw new IllegalArgumentException(String.format("Expected type String or Select; got type [%s] with value [%s]",
|
||||
query.getClass(), query));
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Expected type String or Select; got type [%s] with value [%s]", query.getClass(), query));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,7 +23,6 @@ import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.repository.MapId;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
|
||||
import org.springframework.data.mapping.model.BeanWrapper;
|
||||
import org.springframework.data.repository.core.support.AbstractEntityInformation;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -61,8 +60,9 @@ public class MappingCassandraEntityInformation<T, ID extends Serializable> exten
|
||||
Assert.notNull(entity);
|
||||
|
||||
CassandraPersistentProperty idProperty = entityMetadata.getIdProperty();
|
||||
|
||||
if (idProperty != null) {
|
||||
return (ID) BeanWrapper.create(entity, null).getProperty(idProperty);
|
||||
return (ID) entityMetadata.getIdentifierAccessor(entity).getIdentifier();
|
||||
}
|
||||
|
||||
return (ID) converter.getId(entity, entityMetadata);
|
||||
@@ -71,7 +71,8 @@ public class MappingCassandraEntityInformation<T, ID extends Serializable> exten
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Class<ID> getIdType() {
|
||||
return (Class<ID>) (entityMetadata.getIdProperty() == null ? MapId.class : entityMetadata.getIdProperty().getType());
|
||||
return (Class<ID>) (entityMetadata.getIdProperty() == null ? MapId.class
|
||||
: entityMetadata.getIdProperty().getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
Reference in New Issue
Block a user