wip
This commit is contained in:
@@ -22,8 +22,8 @@ import org.springframework.core.convert.support.GenericConversionService;
|
||||
import org.springframework.data.convert.EntityInstantiators;
|
||||
|
||||
/**
|
||||
* Base class for {@link CassandraConverter} implementations. Sets up a {@link GenericConversionService} and populates
|
||||
* basic converters.
|
||||
* Base class for {@link CassandraConverter} implementations. Sets up a {@link GenericConversionService} and
|
||||
* populates basic converters.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
|
||||
@@ -28,6 +28,6 @@ import org.springframework.data.convert.EntityConverter;
|
||||
public interface CassandraConverter extends
|
||||
EntityConverter<CassandraPersistentEntity<?>, CassandraPersistentProperty, Object, Object> {
|
||||
|
||||
// TODO: move this method to a more appropriate location
|
||||
CreateTableSpecification getCreateTableSpecification(CassandraPersistentEntity<?> entity);
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import java.nio.ByteBuffer;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.util.CqlUtils;
|
||||
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
|
||||
import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
|
||||
@@ -50,8 +50,8 @@ import com.datastax.driver.core.querybuilder.Update;
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter implements ApplicationContextAware,
|
||||
BeanClassLoaderAware {
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter implements CassandraConverter,
|
||||
ApplicationContextAware, BeanClassLoaderAware {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(MappingCassandraConverter.class);
|
||||
|
||||
@@ -114,7 +114,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
this.spELContext = new SpELContext(this.spELContext, applicationContext);
|
||||
}
|
||||
|
||||
private <S extends Object> S readRowInternal(final CassandraPersistentEntity<S> entity, final Row row) {
|
||||
protected <S extends Object> S readRowInternal(final CassandraPersistentEntity<S> entity, final Row row) {
|
||||
|
||||
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
|
||||
|
||||
@@ -127,27 +127,40 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
S instance = instantiator.createInstance(entity, parameterProvider);
|
||||
|
||||
final BeanWrapper<CassandraPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
final S result = wrapper.getBean();
|
||||
S result = wrapper.getBean();
|
||||
|
||||
// Set properties not already set in the constructor
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
boolean isConstructorProperty = entity.isConstructorArgument(prop);
|
||||
boolean hasValueForProperty = row.getColumnDefinitions().contains(prop.getColumnName());
|
||||
|
||||
if (!hasValueForProperty || isConstructorProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = propertyProvider.getPropertyValue(prop);
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
MappingCassandraConverter.this.handlePropertyRead(row, entity, prop, propertyProvider, wrapper);
|
||||
}
|
||||
});
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected void handlePropertyRead(final Row row, final CassandraPersistentEntity<?> entity,
|
||||
final CassandraPersistentProperty prop,
|
||||
final PropertyValueProvider<CassandraPersistentProperty> propertyProvider, final BeanWrapper<?, ?> wrapper) {
|
||||
|
||||
if (entity.isConstructorArgument(prop)) { // skip 'cause prop was set in ctor
|
||||
return;
|
||||
}
|
||||
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
// TODO: handle composite primary key properties via recursion into this method
|
||||
}
|
||||
|
||||
boolean hasValueForProperty = row.getColumnDefinitions().contains(prop.getColumnName());
|
||||
if (!hasValueForProperty) {
|
||||
return;
|
||||
}
|
||||
|
||||
Object obj = propertyProvider.getPropertyValue(prop);
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
}
|
||||
|
||||
public void setUseFieldAccessOnly(boolean useFieldAccessOnly) {
|
||||
this.useFieldAccessOnly = useFieldAccessOnly;
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@ import org.springframework.cassandra.core.PrimaryKeyType;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.mapping.Association;
|
||||
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@@ -48,7 +48,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
* @param simpleTypeHolder
|
||||
*/
|
||||
public BasicCassandraPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@@ -67,6 +67,24 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
return getField().getType().isAnnotationPresent(CompositePrimaryKey.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getCompositePrimaryKeyType() {
|
||||
if (!isCompositePrimaryKey()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return getField().getType();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
|
||||
if (!isCompositePrimaryKey()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (CassandraPersistentEntity<?>) ClassTypeInformation.from(getCompositePrimaryKeyType());
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
|
||||
// first check @Column annotation
|
||||
|
||||
@@ -18,87 +18,136 @@ package org.springframework.data.cassandra.mapping;
|
||||
import java.beans.PropertyDescriptor;
|
||||
import java.lang.reflect.Field;
|
||||
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.cassandra.core.Ordering;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* {@link CassandraPersistentProperty} caching access to {@link #isIdProperty()} and {@link #getColumnName()}.
|
||||
* {@link BasicCassandraPersistentProperty} subclass that caches call results from the superclass.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public class CachingCassandraPersistentProperty extends BasicCassandraPersistentProperty {
|
||||
|
||||
private Boolean isIdProperty;
|
||||
private String columnName;
|
||||
private Boolean isIndexed;
|
||||
private Boolean isPartitioned;
|
||||
private Boolean isCompositePrimaryKey;
|
||||
private Boolean isPartitionKeyColumn;
|
||||
private Boolean isClusterKeyColumn;
|
||||
private Boolean isPrimaryKeyColumn;
|
||||
private String columnName;
|
||||
private Ordering ordering;
|
||||
private boolean orderingCached = false;
|
||||
private DataType dataType;
|
||||
private Class<?> compositePrimaryKeyType;
|
||||
private CassandraPersistentEntity<?> compositePrimaryKeyEntity;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CachingCassandraPersistentProperty}.
|
||||
*
|
||||
* @param field
|
||||
* @param propertyDescriptor
|
||||
* @param owner
|
||||
* @param simpleTypeHolder
|
||||
*/
|
||||
public CachingCassandraPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
super(field, propertyDescriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isIdProperty()
|
||||
*/
|
||||
@Override
|
||||
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
|
||||
|
||||
if (compositePrimaryKeyEntity == null) {
|
||||
compositePrimaryKeyEntity = super.getCompositePrimaryKeyEntity();
|
||||
}
|
||||
return compositePrimaryKeyEntity;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getCompositePrimaryKeyType() {
|
||||
|
||||
if (compositePrimaryKeyType == null) {
|
||||
compositePrimaryKeyType = super.getCompositePrimaryKeyType();
|
||||
}
|
||||
return compositePrimaryKeyType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClusterKeyColumn() {
|
||||
|
||||
if (isClusterKeyColumn == null) {
|
||||
isClusterKeyColumn = super.isClusterKeyColumn();
|
||||
}
|
||||
return isClusterKeyColumn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPrimaryKeyColumn() {
|
||||
|
||||
if (isPrimaryKeyColumn == null) {
|
||||
isPrimaryKeyColumn = super.isPrimaryKeyColumn();
|
||||
}
|
||||
return isPrimaryKeyColumn;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DataType getDataType() {
|
||||
|
||||
if (dataType == null) {
|
||||
dataType = super.getDataType();
|
||||
}
|
||||
return dataType;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Ordering getOrdering() {
|
||||
|
||||
if (!orderingCached) {
|
||||
ordering = super.getOrdering();
|
||||
orderingCached = true;
|
||||
}
|
||||
return ordering;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isCompositePrimaryKey() {
|
||||
|
||||
if (isCompositePrimaryKey == null) {
|
||||
isCompositePrimaryKey = super.isCompositePrimaryKey();
|
||||
}
|
||||
return isCompositePrimaryKey;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isIdProperty() {
|
||||
|
||||
if (this.isIdProperty == null) {
|
||||
this.isIdProperty = super.isIdProperty();
|
||||
if (isIdProperty == null) {
|
||||
isIdProperty = super.isIdProperty();
|
||||
}
|
||||
|
||||
return this.isIdProperty;
|
||||
return isIdProperty;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#getFieldName()
|
||||
*/
|
||||
@Override
|
||||
public String getColumnName() {
|
||||
|
||||
if (this.columnName == null) {
|
||||
this.columnName = super.getColumnName();
|
||||
if (columnName == null) {
|
||||
columnName = super.getColumnName();
|
||||
}
|
||||
|
||||
return this.columnName;
|
||||
return columnName;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isIndexed()
|
||||
*/
|
||||
@Override
|
||||
public boolean isIndexed() {
|
||||
|
||||
if (this.isIndexed == null) {
|
||||
this.isIndexed = super.isIndexed();
|
||||
if (isIndexed == null) {
|
||||
isIndexed = super.isIndexed();
|
||||
}
|
||||
|
||||
return this.isIndexed;
|
||||
return isIndexed;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.mongodb.core.mapping.BasicCassandraPersistentProperty#isPartitioned()
|
||||
*/
|
||||
@Override
|
||||
public boolean isPartitionKeyColumn() {
|
||||
|
||||
if (this.isPartitioned == null) {
|
||||
this.isPartitioned = super.isPartitionKeyColumn();
|
||||
if (isPartitionKeyColumn == null) {
|
||||
isPartitionKeyColumn = super.isPartitionKeyColumn();
|
||||
}
|
||||
|
||||
return this.isPartitioned;
|
||||
return isPartitionKeyColumn;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,13 +27,14 @@ import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link MappingContext} for Cassandra using {@link BasicCassandraPersistentEntity} and
|
||||
* {@link BasicCassandraPersistentProperty} as primary abstractions.
|
||||
* Default implementation of a {@link MappingContext} for Cassandra using {@link CassandraPersistentEntity} and
|
||||
* {@link CassandraPersistentProperty} as primary abstractions.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public class CassandraMappingContext extends
|
||||
AbstractMappingContext<BasicCassandraPersistentEntity<?>, CassandraPersistentProperty> implements
|
||||
AbstractMappingContext<CassandraPersistentEntity<?>, CassandraPersistentProperty> implements
|
||||
ApplicationContextAware {
|
||||
|
||||
private ApplicationContext context;
|
||||
@@ -47,12 +48,17 @@ public class CassandraMappingContext extends
|
||||
|
||||
@Override
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
BasicCassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
return createPersistentProperty(field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder);
|
||||
}
|
||||
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
return new CachingCassandraPersistentProperty(field, descriptor, owner, simpleTypeHolder);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> BasicCassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
protected <T> CassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
BasicCassandraPersistentEntity<T> entity = new BasicCassandraPersistentEntity<T>(typeInformation);
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import org.springframework.data.mapping.PersistentEntity;
|
||||
import org.springframework.data.mapping.model.MutablePersistentEntity;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link PersistentEntity} abstraction.
|
||||
@@ -23,7 +24,7 @@ import org.springframework.data.mapping.PersistentEntity;
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public interface CassandraPersistentEntity<T> extends PersistentEntity<T, CassandraPersistentProperty> {
|
||||
public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T, CassandraPersistentProperty> {
|
||||
|
||||
/**
|
||||
* Returns the table name to which the entity shall be persisted.
|
||||
|
||||
@@ -33,6 +33,18 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
|
||||
*/
|
||||
boolean isCompositePrimaryKey();
|
||||
|
||||
/**
|
||||
* Returns the type of the composite primary key class of this entity, or null if this class does not use a composite
|
||||
* primary key.
|
||||
*/
|
||||
Class<?> getCompositePrimaryKeyType();
|
||||
|
||||
/**
|
||||
* Returns a {@link CassandraPersistentEntity} representing the composite primary key class of this entity, or null if
|
||||
* this class does not use a composite primary key.
|
||||
*/
|
||||
CassandraPersistentEntity<?> getCompositePrimaryKeyEntity();
|
||||
|
||||
/**
|
||||
* The name of the column to which a property is persisted.
|
||||
*/
|
||||
|
||||
@@ -33,7 +33,7 @@ import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Update;
|
||||
|
||||
/**
|
||||
* Utilties to convert Cassandra Annotated objects to Queries and CQL.
|
||||
* Utilities to convert Cassandra Annotated objects to Queries and CQL.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author David Webb
|
||||
|
||||
@@ -28,9 +28,9 @@ import org.springframework.data.cassandra.mapping.BasicCassandraPersistentEntity
|
||||
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
|
||||
import org.springframework.data.cassandra.mapping.Column;
|
||||
import org.springframework.data.cassandra.mapping.PrimaryKey;
|
||||
import org.springframework.data.mapping.model.SimpleTypeHolder;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
@@ -81,6 +81,6 @@ public class BasicCassandraPersistentPropertyIntegrationTests {
|
||||
}
|
||||
|
||||
private CassandraPersistentProperty getPropertyFor(Field field) {
|
||||
return new BasicCassandraPersistentProperty(field, null, entity, new SimpleTypeHolder());
|
||||
return new BasicCassandraPersistentProperty(field, null, entity, new CassandraSimpleTypeHolder());
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user