DATACASS-93 - persistent properties now use CqlIdentifier & legacy tests pass
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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>() {
|
||||
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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());
|
||||
|
||||
|
||||
@@ -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"));
|
||||
}
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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());
|
||||
|
||||
Reference in New Issue
Block a user