DATACASS-93 - persistent properties now use CqlIdentifier & legacy tests pass

This commit is contained in:
Matthew Adams
2014-02-19 20:17:51 -06:00
parent 5cd73864fd
commit 7021419984
12 changed files with 91 additions and 45 deletions

View File

@@ -66,8 +66,8 @@ public class DefaultCassandraRowValueProvider implements CassandraRowValueProvid
return evaluator.evaluate(expression);
}
String columnName = property.getColumnName();
if (source.isNull(property.getColumnName())) {
String columnName = property.getColumnName().toCql();
if (source.isNull(columnName)) {
return null;
}
@@ -133,6 +133,7 @@ public class DefaultCassandraRowValueProvider implements CassandraRowValueProvid
return (T) source.getBytes(columnName);
}
@Override
public Row getRow() {
return source;
}

View File

@@ -165,7 +165,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
return;
}
if (!row.getRow().getColumnDefinitions().contains(prop.getColumnName())) {
if (!row.getRow().getColumnDefinitions().contains(prop.getColumnName().toCql())) {
return;
}
@@ -246,7 +246,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
}
if (value != null) {
insert.value(prop.getColumnName(), value);
insert.value(prop.getColumnName().toCql(), value);
}
}
});
@@ -276,9 +276,9 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
if (value != null) {
if (prop.isIdProperty() || entity.isCompositePrimaryKey()) {
update.where(QueryBuilder.eq(prop.getColumnName(), value));
update.where(QueryBuilder.eq(prop.getColumnName().toCql(), value));
} else {
update.with(QueryBuilder.set(prop.getColumnName(), value));
update.with(QueryBuilder.set(prop.getColumnName().toCql(), value));
}
}
}
@@ -309,7 +309,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
return;
}
where.and(QueryBuilder.eq(idProperty.getColumnName(), idValue));
where.and(QueryBuilder.eq(idProperty.getColumnName().toCql(), idValue));
}
@SuppressWarnings("unchecked")

View File

@@ -262,7 +262,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
}
Select select = QueryBuilder.select().all().from(entity.getTableName().toCql());
select.where(QueryBuilder.in(entity.getIdProperty().getColumnName(), CollectionUtils.toArray(ids)));
select.where(QueryBuilder.in(entity.getIdProperty().getColumnName().toCql(), CollectionUtils.toArray(ids)));
return select(select.getQueryString(), type);
}
@@ -304,7 +304,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
@Override
public void doWithPersistentProperty(CassandraPersistentProperty p) {
clauseCallback.doWithClause(QueryBuilder.eq(p.getColumnName(),
clauseCallback.doWithClause(QueryBuilder.eq(p.getColumnName().toCql(),
idWrapper.getProperty(p, p.getActualType(), useFieldAccessOnly)));
}
});
@@ -312,7 +312,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
return;
}
clauseCallback.doWithClause(QueryBuilder.eq(idProperty.getColumnName(), id));
clauseCallback.doWithClause(QueryBuilder.eq(idProperty.getColumnName().toCql(), id));
}
protected void appendIdCriteria(final com.datastax.driver.core.querybuilder.Select.Where where,

View File

@@ -34,9 +34,6 @@ import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
import org.springframework.expression.ParserContext;
import org.springframework.expression.spel.standard.SpelExpressionParser;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
@@ -54,9 +51,9 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
protected CqlIdentifier tableName;
protected CassandraMappingContext mappingContext;
protected final StandardEvaluationContext spelContext;
protected final SpelExpressionParser spelParser;
protected StandardEvaluationContext spelContext;
protected CassandraPersistentEntityMetadataVerifier verifier = DEFAULT_VERIFIER;
protected ApplicationContext context;
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation) {
this(typeInformation, null);
@@ -84,8 +81,6 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
super(typeInformation, CassandraPersistentPropertyComparator.IT);
this.spelParser = new SpelExpressionParser();
this.spelContext = new StandardEvaluationContext();
this.mappingContext = mappingContext;
setVerifier(verifier);
@@ -99,7 +94,7 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
return cqlId(getType().getSimpleName(), anno == null ? false : anno.forceQuote());
}
return cqlId(SpelUtils.evaluate(anno.value(), spelContext), anno.forceQuote());
return cqlId(spelContext == null ? anno.value() : SpelUtils.evaluate(anno.value(), spelContext), anno.forceQuote());
}
@Override
@@ -113,14 +108,15 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
}
@Override
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
public void setApplicationContext(ApplicationContext context) throws BeansException {
Assert.notNull(context);
this.context = context;
spelContext = new StandardEvaluationContext();
spelContext.addPropertyAccessor(new BeanFactoryAccessor());
spelContext.setBeanResolver(new BeanFactoryResolver(applicationContext));
spelContext.setRootObject(applicationContext);
// this is the earliest time at which we can do this because the table name value may contain a SpEL expression
getTableName();
spelContext.setBeanResolver(new BeanFactoryResolver(context));
spelContext.setRootObject(context);
}
@Override
@@ -203,4 +199,9 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
public void setVerifier(CassandraPersistentEntityMetadataVerifier verifier) {
this.verifier = verifier;
}
@Override
public ApplicationContext getApplicationContext() {
return context;
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.cassandra.mapping;
import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
@@ -23,12 +25,20 @@ import java.util.Set;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.expression.BeanFactoryAccessor;
import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.cassandra.util.SpelUtils;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.spel.support.StandardEvaluationContext;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.datastax.driver.core.DataType;
@@ -37,9 +47,13 @@ import com.datastax.driver.core.DataType;
* Cassandra specific {@link org.springframework.data.mapping.model.AnnotationBasedPersistentProperty} implementation.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentProperty<CassandraPersistentProperty>
implements CassandraPersistentProperty {
implements CassandraPersistentProperty, ApplicationContextAware {
protected ApplicationContext context;
protected StandardEvaluationContext spelContext;
/**
* Creates a new {@link BasicCassandraPersistentProperty}.
@@ -53,6 +67,22 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
if (owner != null && owner.getApplicationContext() != null) {
setApplicationContext(owner.getApplicationContext());
}
}
@Override
public void setApplicationContext(ApplicationContext context) {
Assert.notNull(context);
this.context = context;
spelContext = new StandardEvaluationContext();
spelContext.addPropertyAccessor(new BeanFactoryAccessor());
spelContext.setBeanResolver(new BeanFactoryResolver(context));
spelContext.setRootObject(context);
}
@Override
@@ -83,9 +113,9 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
}
@Override
public String getColumnName() {
public CqlIdentifier getColumnName() {
List<String> columnNames = getColumnNames();
List<CqlIdentifier> columnNames = getColumnNames();
if (columnNames.size() != 1) {
throw new IllegalStateException("property does not have a single column mapping");
}
@@ -226,9 +256,9 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
}
@Override
public List<String> getColumnNames() {
public List<CqlIdentifier> getColumnNames() {
final List<String> columnNames = new ArrayList<String>();
List<CqlIdentifier> columnNames = new ArrayList<CqlIdentifier>();
if (isCompositePrimaryKey()) {
addCompositePrimaryKeyColumnNames(getCompositePrimaryKeyEntity(), columnNames);
@@ -238,24 +268,26 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
// else not a composite primary key property -- first check @Column annotation
Column column = findAnnotation(Column.class);
if (column != null && StringUtils.hasText(column.value())) {
columnNames.add(column.value());
columnNames.add(cqlId(spelContext == null ? column.value() : SpelUtils.evaluate(column.value(), spelContext),
column.forceQuote()));
return columnNames;
}
// else check @PrimaryKeyColumn annotation
PrimaryKeyColumn pk = findAnnotation(PrimaryKeyColumn.class);
if (pk != null && StringUtils.hasText(pk.name())) {
columnNames.add(pk.name());
columnNames.add(cqlId(spelContext == null ? pk.name() : SpelUtils.evaluate(pk.name(), spelContext),
pk.forceQuote()));
return columnNames;
}
// else default
columnNames.add(field.getName().toLowerCase()); // TODO: replace with naming strategy class
columnNames.add(cqlId(field.getName())); // TODO: replace with naming strategy class
return columnNames;
}
protected void addCompositePrimaryKeyColumnNames(CassandraPersistentEntity<?> compositePrimaryKeyEntity,
final List<String> columnNames) {
final List<CqlIdentifier> columnNames) {
compositePrimaryKeyEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {

View File

@@ -20,6 +20,7 @@ import java.lang.reflect.Field;
import java.util.List;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.data.util.TypeInformation;
import com.datastax.driver.core.DataType;
@@ -38,8 +39,8 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
private Boolean isPartitionKeyColumn;
private Boolean isClusterKeyColumn;
private Boolean isPrimaryKeyColumn;
private String columnName;
private List<String> columnNames;
private CqlIdentifier columnName;
private List<CqlIdentifier> columnNames;
private Ordering ordering;
private boolean orderingCached = false;
private DataType dataType;
@@ -128,7 +129,7 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
}
@Override
public String getColumnName() {
public CqlIdentifier getColumnName() {
if (columnName == null) {
columnName = super.getColumnName();
@@ -155,7 +156,7 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
}
@Override
public List<String> getColumnNames() {
public List<CqlIdentifier> getColumnNames() {
if (columnNames == null) {
columnNames = super.getColumnNames();
}

View File

@@ -18,6 +18,7 @@ package org.springframework.data.cassandra.mapping;
import java.util.List;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.MutablePersistentEntity;
@@ -46,4 +47,6 @@ public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T,
void setTableName(CqlIdentifier tableName);
CassandraMappingContext getMappingContext();
ApplicationContext getApplicationContext();
}

View File

@@ -18,6 +18,8 @@ package org.springframework.data.cassandra.mapping;
import java.util.List;
import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.TypeInformation;
@@ -30,7 +32,8 @@ import com.datastax.driver.core.DataType;
* @author Matthew T. Adams
* @author David T. Webb
*/
public interface CassandraPersistentProperty extends PersistentProperty<CassandraPersistentProperty> {
public interface CassandraPersistentProperty extends PersistentProperty<CassandraPersistentProperty>,
ApplicationContextAware {
/**
* Whether the property is a composite primary key.
@@ -59,13 +62,13 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
* knows that the property is mapped to a single column. Throws {@link IllegalStateException} if this property is
* mapped to multiple columns.
*/
String getColumnName();
CqlIdentifier getColumnName();
/**
* The names of the columns to which the property is persisted if this is a composite primary key property. Never
* returns null.
*/
List<String> getColumnNames();
List<CqlIdentifier> getColumnNames();
/**
* The ordering (ascending or descending) for the column. Valid only for primary key columns; returns null for

View File

@@ -52,7 +52,7 @@ public abstract class CqlUtils {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
String columnName = prop.getColumnName();
String columnName = prop.getColumnName().toCql();
DataType columnDataType = prop.getDataType();
ColumnMetadata columnMetadata = table.getColumn(columnName.toLowerCase());

View File

@@ -53,6 +53,7 @@ public class BasicCassandraPersistentEntityIntegrationTests {
BasicCassandraPersistentEntity<Area> entity = new BasicCassandraPersistentEntity<Area>(
ClassTypeInformation.from(Area.class));
entity.setApplicationContext(context);
assertThat(entity.getTableName().toCql(), is("a123"));
}

View File

@@ -64,7 +64,7 @@ public class BasicCassandraPersistentPropertyIntegrationTests {
public void usesAnnotatedColumnName() {
Field field = ReflectionUtils.findField(Timeline.class, "text");
assertThat(getPropertyFor(field).getColumnName(), is("message"));
assertThat(getPropertyFor(field).getColumnName().toCql(), is("message"));
}
@Test
@@ -77,7 +77,7 @@ public class BasicCassandraPersistentPropertyIntegrationTests {
@Test
public void returnsPropertyNameForUnannotatedProperty() {
Field field = ReflectionUtils.findField(Timeline.class, "time");
assertThat(getPropertyFor(field).getColumnName(), is("time"));
assertThat(getPropertyFor(field).getColumnName().toCql(), is("time"));
}
private CassandraPersistentProperty getPropertyFor(Field field) {

View File

@@ -17,6 +17,7 @@ package org.springframework.data.cassandra.test.integration.mapping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId;
import java.io.Serializable;
import java.lang.reflect.Field;
@@ -28,6 +29,7 @@ import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.cassandra.core.cql.CqlIdentifier;
import org.springframework.cassandra.core.keyspace.ColumnSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty;
@@ -59,6 +61,8 @@ public class CassandraCompositePrimaryKeyIntegrationTests {
@PrimaryKeyClass
static class Key implements Serializable {
private static final long serialVersionUID = 1L;
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
String z;
@@ -130,10 +134,10 @@ public class CassandraCompositePrimaryKeyIntegrationTests {
assertTrue(property.isIdProperty());
assertTrue(property.isCompositePrimaryKey());
List<String> expectedColumnNames = Arrays.asList(new String[] { "z", "a" });
List<CqlIdentifier> expectedColumnNames = Arrays.asList(new CqlIdentifier[] { cqlId("z"), cqlId("a") });
assertTrue(expectedColumnNames.equals(property.getColumnNames()));
List<String> actualColumnNames = new ArrayList<String>();
List<CqlIdentifier> actualColumnNames = new ArrayList<CqlIdentifier>();
List<CassandraPersistentProperty> properties = property.getCompositePrimaryKeyProperties();
for (CassandraPersistentProperty p : properties) {
actualColumnNames.addAll(p.getColumnNames());