@@ -83,7 +83,6 @@ public class BasicCassandraMappingContext
|
||||
* Creates a new {@link BasicCassandraMappingContext}.
|
||||
*/
|
||||
public BasicCassandraMappingContext() {
|
||||
|
||||
setCustomConversions(new CustomConversions(Collections.EMPTY_LIST));
|
||||
setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER);
|
||||
}
|
||||
@@ -95,7 +94,6 @@ public class BasicCassandraMappingContext
|
||||
* @since 1.5
|
||||
*/
|
||||
public void setCustomConversions(CustomConversions customConversions) {
|
||||
|
||||
Assert.notNull(customConversions, "CustomConversions must not be null");
|
||||
|
||||
this.customConversions = customConversions;
|
||||
@@ -127,6 +125,7 @@ public class BasicCassandraMappingContext
|
||||
if (includePrimaryKeyTypes) {
|
||||
return super.getPersistentEntities();
|
||||
}
|
||||
|
||||
return Collections.unmodifiableSet(nonPrimaryKeyEntities);
|
||||
}
|
||||
|
||||
@@ -296,55 +295,50 @@ public class BasicCassandraMappingContext
|
||||
public DataType getDataType(Class<?> type) {
|
||||
|
||||
return (customConversions.hasCustomWriteTarget(type)
|
||||
? getDataTypeFor(customConversions.getCustomWriteTarget(type))
|
||||
: getDataTypeFor(type));
|
||||
? getDataTypeFor(customConversions.getCustomWriteTarget(type)) : getDataTypeFor(type));
|
||||
}
|
||||
|
||||
public void setMapping(Mapping mapping) {
|
||||
|
||||
Assert.notNull(mapping, "Mapping must not be null");
|
||||
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
protected void processMappingOverrides() {
|
||||
|
||||
if (mapping != null) {
|
||||
for (EntityMapping entityMapping : mapping.getEntityMappings()) {
|
||||
|
||||
if (entityMapping == null) {
|
||||
continue;
|
||||
}
|
||||
if (entityMapping != null) {
|
||||
String entityClassName = entityMapping.getEntityClassName();
|
||||
|
||||
String entityClassName = entityMapping.getEntityClassName();
|
||||
try {
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
|
||||
|
||||
try {
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
|
||||
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
if (entity == null) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"Unknown persistent entity class name [%s]", entityClassName));
|
||||
}
|
||||
|
||||
if (entity == null) {
|
||||
throw new IllegalStateException(String.format("unknown persistent entity class name [%s]", entityClassName));
|
||||
String tableName = entityMapping.getTableName();
|
||||
|
||||
if (StringUtils.hasText(tableName)) {
|
||||
entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote())));
|
||||
}
|
||||
|
||||
processMappingOverrides(entity, entityMapping);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"unknown persistent entity name [%s]", entityClassName), e);
|
||||
}
|
||||
|
||||
String tableName = entityMapping.getTableName();
|
||||
|
||||
if (StringUtils.hasText(tableName)) {
|
||||
entity.setTableName(cqlId(tableName, Boolean.valueOf(entityMapping.getForceQuote())));
|
||||
}
|
||||
|
||||
processMappingOverrides(entity, entityMapping);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"unknown persistent entity name [%s]", entityClassName), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {
|
||||
|
||||
for (PropertyMapping mapping : entityMapping.getPropertyMappings().values()) {
|
||||
processMappingOverride(entity, mapping);
|
||||
}
|
||||
@@ -356,7 +350,7 @@ public class BasicCassandraMappingContext
|
||||
|
||||
if (property == null) {
|
||||
throw new IllegalArgumentException(String.format("Entity class [%s] has no persistent property named [%s]",
|
||||
entity.getType().getName(), mapping.getPropertyName()));
|
||||
entity.getType().getName(), mapping.getPropertyName()));
|
||||
}
|
||||
|
||||
boolean forceQuote = false;
|
||||
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.mapping.model.MappingException;
|
||||
*
|
||||
* @author Matthew T Adams
|
||||
* @author David Webb
|
||||
* @author John Blum
|
||||
*/
|
||||
public class BasicCassandraPersistentEntityMetadataVerifier implements CassandraPersistentEntityMetadataVerifier {
|
||||
|
||||
@@ -40,14 +41,15 @@ public class BasicCassandraPersistentEntityMetadataVerifier implements Cassandra
|
||||
protected boolean strict = false;
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("all")
|
||||
public void verify(CassandraPersistentEntity<?> entity) throws MappingException {
|
||||
|
||||
if(entity.getType().isInterface()){
|
||||
if (entity.getType().isInterface()){
|
||||
return;
|
||||
}
|
||||
|
||||
VerifierMappingExceptions exceptions = new VerifierMappingExceptions(entity,
|
||||
String.format("Mapping Exceptions from BasicCassandraPersistentEntityMetadataVerifier for %s", entity.getName()));
|
||||
VerifierMappingExceptions exceptions = new VerifierMappingExceptions(entity, String.format(
|
||||
"Mapping Exceptions from BasicCassandraPersistentEntityMetadataVerifier for %s", entity.getName()));
|
||||
|
||||
final List<CassandraPersistentProperty> idProperties = new ArrayList<CassandraPersistentProperty>();
|
||||
final List<CassandraPersistentProperty> compositePrimaryKeys = new ArrayList<CassandraPersistentProperty>();
|
||||
@@ -55,49 +57,41 @@ public class BasicCassandraPersistentEntityMetadataVerifier implements Cassandra
|
||||
final List<CassandraPersistentProperty> clusterKeyColumns = new ArrayList<CassandraPersistentProperty>();
|
||||
final List<CassandraPersistentProperty> primaryKeyColumns = new ArrayList<CassandraPersistentProperty>();
|
||||
|
||||
/*
|
||||
* Determine how this type is annotated
|
||||
*/
|
||||
Class<?> thisType = entity.getType();
|
||||
Class<?> entityType = entity.getType();
|
||||
|
||||
boolean isTable = (thisType.isAnnotationPresent(Table.class) || thisType.isAnnotationPresent(Persistent.class));
|
||||
boolean isPrimaryKeyClass = thisType.isAnnotationPresent(PrimaryKeyClass.class);
|
||||
boolean isTable = (entityType.isAnnotationPresent(Table.class)
|
||||
|| entityType.isAnnotationPresent(Persistent.class));
|
||||
|
||||
/*
|
||||
* Ensure that this is not both a @Table(@Persistent) and a @PrimaryKey
|
||||
*/
|
||||
boolean isPrimaryKeyClass = entityType.isAnnotationPresent(PrimaryKeyClass.class);
|
||||
|
||||
// Ensure entity is not both a @Table(@Persistent) and a @PrimaryKey
|
||||
if (isTable && isPrimaryKeyClass) {
|
||||
exceptions.add(new MappingException("Entity cannot be of type Table and PrimaryKey"));
|
||||
throw exceptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that this is either a @Table(@Persistent) or a @PrimaryKey
|
||||
*/
|
||||
// Ensure entity is either a @Table/@Persistent or a @PrimaryKey
|
||||
if (!isTable && !isPrimaryKeyClass) {
|
||||
exceptions.add(new MappingException(
|
||||
"Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation"));
|
||||
"Cassandra entities must have the @Table, @Persistent or @PrimaryKeyClass Annotation"));
|
||||
throw exceptions;
|
||||
}
|
||||
|
||||
/*
|
||||
* Parse the properties
|
||||
*/
|
||||
// Parse entity properties
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
|
||||
if (p.isIdProperty()) {
|
||||
idProperties.add(p);
|
||||
} else if (p.isCompositePrimaryKey()) {
|
||||
compositePrimaryKeys.add(p);
|
||||
} else if (p.isPartitionKeyColumn()) {
|
||||
partitionKeyColumns.add(p);
|
||||
primaryKeyColumns.add(p);
|
||||
} else if (p.isClusterKeyColumn()) {
|
||||
clusterKeyColumns.add(p);
|
||||
primaryKeyColumns.add(p);
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty property) {
|
||||
if (property.isIdProperty()) {
|
||||
idProperties.add(property);
|
||||
} else if (property.isClusterKeyColumn()) {
|
||||
clusterKeyColumns.add(property);
|
||||
primaryKeyColumns.add(property);
|
||||
} else if (property.isCompositePrimaryKey()) {
|
||||
compositePrimaryKeys.add(property);
|
||||
} else if (property.isPartitionKeyColumn()) {
|
||||
partitionKeyColumns.add(property);
|
||||
primaryKeyColumns.add(property);
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -106,92 +100,51 @@ public class BasicCassandraPersistentEntityMetadataVerifier implements Cassandra
|
||||
final int partitionKeyColumnCount = partitionKeyColumns.size();
|
||||
final int primaryKeyColumnCount = primaryKeyColumns.size();
|
||||
|
||||
/*
|
||||
* Perform rules verification on PrimaryKeyClass
|
||||
*/
|
||||
// Perform rules verification on PrimaryKeyClass
|
||||
if (isPrimaryKeyClass) {
|
||||
|
||||
/*
|
||||
* Must have at least 1 attribute annotated with @PrimaryKeyColumn
|
||||
*/
|
||||
// Must have at least 1 attribute annotated with @PrimaryKeyColumn
|
||||
if (primaryKeyColumnCount == 0) {
|
||||
exceptions.add(new MappingException(String.format(
|
||||
"composite primary key type [%s] has no fields annotated with @%s", entity.getType().getName(),
|
||||
"Composite primary key type [%s] has no fields annotated with @%s", entity.getType().getName(),
|
||||
PrimaryKeyColumn.class.getSimpleName())));
|
||||
}
|
||||
|
||||
/*
|
||||
* At least one of the PrimaryKeyColumns must have a type PARTIONED
|
||||
*/
|
||||
// At least one of the PrimaryKeyColumns must have a type PARTIONED
|
||||
if (partitionKeyColumnCount == 0) {
|
||||
exceptions.add(new MappingException(
|
||||
"At least one of the @PrimaryKeyColumn annotation must have a type of PARTITIONED"));
|
||||
"At least one of the @PrimaryKeyColumn annotations must have a type of PARTITIONED"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Cannot have any Id or PrimaryKey Annotations
|
||||
*/
|
||||
// Cannot have any Id or PrimaryKey Annotations
|
||||
if (idPropertyCount > 0) {
|
||||
exceptions.add(new MappingException(
|
||||
"Annotations @Id and @PrimaryKey are invalid for type annotated with @PrimaryKeyClass"));
|
||||
"Annotations @Id and @PrimaryKey are invalid for type annotated with @PrimaryKeyClass"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure that PrimaryKeyColumn is a supported Type.
|
||||
*/
|
||||
for (CassandraPersistentProperty p : primaryKeyColumns) {
|
||||
if (CassandraSimpleTypeHolder.getDataTypeFor(p.getType()) == null) {
|
||||
exceptions.add(new MappingException("Fields annotated with @PrimaryKeyColumn must be simple CassandraTypes"));
|
||||
// Ensure that PrimaryKeyColumn is a supported Type.
|
||||
for (CassandraPersistentProperty property : primaryKeyColumns) {
|
||||
if (CassandraSimpleTypeHolder.getDataTypeFor(property.getType()) == null) {
|
||||
exceptions.add(new MappingException(
|
||||
"Fields annotated with @PrimaryKeyColumn must be simple CassandraTypes"));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure PrimaryKeyClass is Serializable
|
||||
*/
|
||||
if (!Serializable.class.isAssignableFrom(thisType)) {
|
||||
// Ensure PrimaryKeyClass is Serializable
|
||||
if (!Serializable.class.isAssignableFrom(entityType)) {
|
||||
exceptions.add(new MappingException("@PrimaryKeyClass must be Serializable"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Ensure PrimaryKeyClass only extends Object
|
||||
*/
|
||||
if (!thisType.getSuperclass().equals(Object.class)) {
|
||||
// Ensure PrimaryKeyClass only extends Object
|
||||
if (!entityType.getSuperclass().equals(Object.class)) {
|
||||
exceptions.add(new MappingException("@PrimaryKeyClass must only extend Object"));
|
||||
}
|
||||
|
||||
/*
|
||||
* Check that PrimaryKeyClass overrides "boolean equals(Object)"
|
||||
*/
|
||||
try {
|
||||
Method equalsMethod = thisType.getDeclaredMethod("equals", Object.class);
|
||||
if (equalsMethod == null || !equalsMethod.getDeclaringClass().equals(thisType)) {
|
||||
throw new NoSuchMethodException();
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
String message = "@PrimaryKeyClass should override 'boolean equals(Object)' method and use all @PrimaryKeyColumn fields";
|
||||
if (strict) {
|
||||
exceptions.add(new MappingException(message, e));
|
||||
} else {
|
||||
log.warn(message);
|
||||
}
|
||||
}
|
||||
// Check that PrimaryKeyClass overrides "boolean equals(Object)"
|
||||
verifyMethodPresent(entityType, "equals", "boolean equals(Object)", exceptions);
|
||||
|
||||
/*
|
||||
* Ensure PrimaryKeyClass overrides "int hashCode()"
|
||||
*/
|
||||
try {
|
||||
Method hashCodeMethod = thisType.getDeclaredMethod("hashCode", (Class<?>[]) null);
|
||||
if (hashCodeMethod == null || !hashCodeMethod.getDeclaringClass().equals(thisType)) {
|
||||
throw new NoSuchMethodException();
|
||||
}
|
||||
} catch (NoSuchMethodException e) {
|
||||
String message = "@PrimaryKeyClass should override 'int hashCode()' method and use all @PrimaryKeyColumn fields";
|
||||
if (strict) {
|
||||
exceptions.add(new MappingException(message, e));
|
||||
} else {
|
||||
log.warn(message);
|
||||
}
|
||||
}
|
||||
// Ensure PrimaryKeyClass overrides "int hashCode()"
|
||||
verifyMethodPresent(entityType, "hashCode", "int hashCode()", exceptions);
|
||||
}
|
||||
|
||||
/*
|
||||
@@ -199,75 +152,88 @@ public class BasicCassandraPersistentEntityMetadataVerifier implements Cassandra
|
||||
*/
|
||||
if (isTable) {
|
||||
|
||||
/*
|
||||
* TODO Verify annotation values with CqlIndentifier
|
||||
*/
|
||||
// TODO Verify annotation values with CqlIndentifier
|
||||
|
||||
/*
|
||||
* Ensure only one PK or at least one partitioned PKC and not both PK(s) & PKC(s)
|
||||
*/
|
||||
// Ensure only one PK or at least one partitioned PK Column and not both PK(s) & PK Column(s) exist
|
||||
if (primaryKeyColumnCount == 0) {
|
||||
/*
|
||||
* Can only have one PK.
|
||||
*/
|
||||
// Can only have one PK
|
||||
if (idPropertyCount != 1) {
|
||||
exceptions
|
||||
.add(new MappingException(String.format(
|
||||
"@Table/@Persistent types must have only one @PrimaryKey attribute, if any. Found %s.",
|
||||
idPropertyCount)));
|
||||
exceptions.add(new MappingException(String.format(
|
||||
"@Table/@Persistent types must have only one @PrimaryKey attribute, if any; Found %s",
|
||||
idPropertyCount)));
|
||||
|
||||
throw exceptions;
|
||||
}
|
||||
/*
|
||||
* Ensure that Id is a supported Type. At the point there is only 1.
|
||||
*/
|
||||
Class<?> typeClass = idProperties.get(0).getType();
|
||||
if (!typeClass.isAnnotationPresent(PrimaryKeyClass.class)
|
||||
&& CassandraSimpleTypeHolder.getDataTypeFor(typeClass) == null) {
|
||||
|
||||
// Ensure that Id is a supported Type. At this point there is only 1.
|
||||
Class<?> idType = idProperties.get(0).getType();
|
||||
|
||||
if (!idType.isAnnotationPresent(PrimaryKeyClass.class)
|
||||
&& CassandraSimpleTypeHolder.getDataTypeFor(idType) == null) {
|
||||
|
||||
exceptions.add(new MappingException(
|
||||
"Fields annotated with @PrimaryKey must be simple CassandraTypes or @PrimaryKeyClass type"));
|
||||
"Fields annotated with @PrimaryKey must be simple CassandraTypes or @PrimaryKeyClass type"));
|
||||
}
|
||||
} else if (idPropertyCount > 0) {
|
||||
/*
|
||||
* Then we have both PK(s) & PKC(s)
|
||||
*/
|
||||
exceptions
|
||||
.add(new MappingException(
|
||||
String
|
||||
.format(
|
||||
"@Table/@Persistent types must not define both @PrimaryKeyColumn field%s (found %s) and @PrimaryKey field%s (found %s)",
|
||||
primaryKeyColumnCount == 1 ? "" : "s", primaryKeyColumnCount, idPropertyCount == 1 ? "" : "s",
|
||||
idPropertyCount)));
|
||||
// Then we have both PK(s) & PK Column(s)
|
||||
exceptions.add(new MappingException(String.format(
|
||||
"@Table/@Persistent types must not define both @PrimaryKeyColumn field(s) (found %s) and @PrimaryKey field(s) (found %s)",
|
||||
primaryKeyColumnCount, idPropertyCount)));
|
||||
|
||||
throw exceptions;
|
||||
} else {
|
||||
/*
|
||||
* We have no PKs & only PKC(s) -- ensure at least one is of type PARTITIONED
|
||||
*/
|
||||
// We have no PKs & only PK Column(s); ensure at least one is of type PARTITIONED
|
||||
if (partitionKeyColumnCount == 0) {
|
||||
exceptions.add(new MappingException(String
|
||||
.format("@Table/@Persistent types must define at least one @PrimaryKeyColumn of type PARTITIONED")));
|
||||
exceptions.add(new MappingException(String.format(
|
||||
"@Table/@Persistent types must define at least one @PrimaryKeyColumn of type PARTITIONED")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Determine whether or not to throw Exception based on errors found
|
||||
*/
|
||||
// Determine whether or not to throw Exception based on errors found
|
||||
if (exceptions.getCount() > 0) {
|
||||
log.error("Exceptions while verifying PersistentEntity", exceptions);
|
||||
throw exceptions;
|
||||
}
|
||||
}
|
||||
|
||||
boolean verifyMethodPresent(Class<?> type, String methodName, String methodDescription,
|
||||
VerifierMappingExceptions exceptions) {
|
||||
try {
|
||||
Method method = type.getDeclaredMethod(methodName, Object.class);
|
||||
|
||||
if (method == null || !method.getDeclaringClass().equals(type)) {
|
||||
throw new NoSuchMethodException();
|
||||
}
|
||||
|
||||
return true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
String message = String.format(
|
||||
"@PrimaryKeyClass should override '%s' method and use all @PrimaryKeyColumn fields",
|
||||
methodDescription);
|
||||
|
||||
if (strict) {
|
||||
exceptions.add(new MappingException(message, e));
|
||||
} else {
|
||||
log.warn(message);
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the strict.
|
||||
* @return the setting for strict.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isStrict() {
|
||||
return strict;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param strict The strict to set.
|
||||
* @param strict boolean setting for strict.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public void setStrict(boolean strict) {
|
||||
this.strict = strict;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import java.lang.reflect.Field;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.cassandra.core.Ordering;
|
||||
@@ -41,6 +42,7 @@ 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.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
@@ -52,6 +54,7 @@ import com.datastax.driver.core.DataType;
|
||||
* @author Matthew T. Adams
|
||||
* @author Antoine Toulme
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentProperty<CassandraPersistentProperty>
|
||||
implements CassandraPersistentProperty, ApplicationContextAware {
|
||||
@@ -154,8 +157,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"unknown type for property [%s], type [%s] in entity [%s]; only primitive types and collections or maps of primitive types are allowed",
|
||||
getName(), getType(), getOwner().getName()));
|
||||
"Unknown type [%s] for property [%s] in entity [%s]; only primitive types and Collections or Maps of primitive types are allowed",
|
||||
getType(), getName(), getOwner().getName()));
|
||||
}
|
||||
|
||||
return dataType;
|
||||
@@ -178,7 +181,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
}
|
||||
|
||||
if (isCollectionLike()) {
|
||||
|
||||
List<TypeInformation<?>> args = getTypeInformation().getTypeArguments();
|
||||
|
||||
ensureTypeArguments(args.size(), 1);
|
||||
@@ -220,20 +222,20 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
return isAnnotationPresent(Indexed.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartitionKeyColumn() {
|
||||
|
||||
PrimaryKeyColumn primaryKeyColumn = findAnnotation(PrimaryKeyColumn.class);
|
||||
|
||||
return (primaryKeyColumn != null && primaryKeyColumn.type() == PrimaryKeyType.PARTITIONED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isClusterKeyColumn() {
|
||||
|
||||
PrimaryKeyColumn primaryKeyColumn = findAnnotation(PrimaryKeyColumn.class);
|
||||
|
||||
return (primaryKeyColumn != null && primaryKeyColumn.type() == PrimaryKeyType.CLUSTERED);
|
||||
return (primaryKeyColumn != null && PrimaryKeyType.CLUSTERED.equals(primaryKeyColumn.type()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isPartitionKeyColumn() {
|
||||
|
||||
PrimaryKeyColumn primaryKeyColumn = findAnnotation(PrimaryKeyColumn.class);
|
||||
|
||||
return (primaryKeyColumn != null && PrimaryKeyType.PARTITIONED.equals(primaryKeyColumn.type()));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -241,12 +243,13 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
return isAnnotationPresent(PrimaryKeyColumn.class);
|
||||
}
|
||||
|
||||
protected DataType getDataTypeFor(DataType.Name typeName) {
|
||||
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(typeName);
|
||||
protected DataType getDataTypeFor(DataType.Name dataTypeName) {
|
||||
|
||||
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(dataTypeName);
|
||||
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"only primitive types are allowed inside collections for the property '%1$s' type is '%2$s' in the entity %3$s",
|
||||
"Only primitive types are allowed inside Collections for property [%1$s] of type [%2$s] in entity [%3$s]",
|
||||
getName(), getType(), getOwner().getName()));
|
||||
}
|
||||
|
||||
@@ -254,11 +257,12 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
}
|
||||
|
||||
protected DataType getDataTypeFor(Class<?> javaType) {
|
||||
|
||||
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(javaType);
|
||||
|
||||
if (dataType == null) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"only primitive types are allowed inside collections for the property '%1$s' type is '%2$s' in the entity %3$s",
|
||||
"Only primitive types are allowed inside Collections for property [%1$s] of type ['%2$s'] in entity [%3$s]",
|
||||
getName(), getType(), getOwner().getName()));
|
||||
}
|
||||
|
||||
@@ -268,8 +272,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
protected void ensureTypeArguments(int args, int expected) {
|
||||
if (args != expected) {
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("expected %1$s of typed arguments for the property '%2$s' type is '%3$s' in the entity %4$s",
|
||||
expected, getName(), getType(), getOwner().getName()));
|
||||
String.format("Expected [%1$s] typed arguments for property ['%2$s'] of type ['%3$s'] in entity [%4$s]",
|
||||
expected, getName(), getType(), getOwner().getName()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -320,7 +324,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
String name = defaultName;
|
||||
|
||||
if (StringUtils.hasText(overriddenName)) {
|
||||
name = (spelContext == null ? overriddenName : SpelUtils.evaluate(overriddenName, spelContext));
|
||||
name = (spelContext != null ? SpelUtils.evaluate(overriddenName, spelContext) : overriddenName);
|
||||
}
|
||||
|
||||
return cqlId(name, forceQuote);
|
||||
@@ -331,11 +335,11 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
|
||||
compositePrimaryKeyEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
if (p.isCompositePrimaryKey()) {
|
||||
addCompositePrimaryKeyColumnNames(p.getCompositePrimaryKeyEntity(), columnNames);
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty property) {
|
||||
if (property.isCompositePrimaryKey()) {
|
||||
addCompositePrimaryKeyColumnNames(property.getCompositePrimaryKeyEntity(), columnNames);
|
||||
} else {
|
||||
columnNames.add(p.getColumnName());
|
||||
columnNames.add(property.getColumnName());
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -353,14 +357,14 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
|
||||
Assert.notNull(columnNames);
|
||||
|
||||
// force calculation of columnNames if not yet known
|
||||
// force calculation of columnNames if not known yet
|
||||
getColumnNames();
|
||||
|
||||
if (this.columnNames.size() != columnNames.size()) {
|
||||
throw new IllegalStateException(String.format(
|
||||
"property [%s] on entity [%s] is mapped to [%s] column%s, but given column name list has size [%s]",
|
||||
getName(), getOwner().getType().getName(), this.columnNames.size(), this.columnNames.size() == 1 ? "" : "s",
|
||||
columnNames.size()));
|
||||
"Property [%s] of entity [%s] is mapped to [%s] column%s, but given column name list has size [%s]",
|
||||
getName(), getOwner().getType().getName(), this.columnNames.size(),
|
||||
this.columnNames.size() == 1 ? "" : "s", columnNames.size()));
|
||||
}
|
||||
|
||||
this.columnNames = this.explicitColumnNames =
|
||||
@@ -390,8 +394,8 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
public List<CassandraPersistentProperty> getCompositePrimaryKeyProperties() {
|
||||
|
||||
if (!isCompositePrimaryKey()) {
|
||||
throw new IllegalStateException(
|
||||
String.format("[%s] does not represent a composite primary key property", getName()));
|
||||
throw new IllegalStateException(String.format(
|
||||
"[%s] does not represent a composite primary key property", getName()));
|
||||
}
|
||||
|
||||
return getCompositePrimaryKeyEntity().getCompositePrimaryKeyProperties();
|
||||
@@ -399,6 +403,7 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
|
||||
@Override
|
||||
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
|
||||
|
||||
CassandraMappingContext mappingContext = getOwner().getMappingContext();
|
||||
|
||||
if (mappingContext == null) {
|
||||
@@ -417,4 +422,9 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
|
||||
protected Association<CassandraPersistentProperty> createAssociation() {
|
||||
return new Association<CassandraPersistentProperty>(this, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isMapLike() {
|
||||
return ClassUtils.isAssignable(Map.class, getType());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2013-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -29,11 +29,12 @@ import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Cassandra specific {@link org.springframework.data.mapping.PersistentProperty} extension.
|
||||
*
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
* @author David T. Webb
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
public interface CassandraPersistentProperty
|
||||
extends PersistentProperty<CassandraPersistentProperty>, ApplicationContextAware {
|
||||
@@ -81,7 +82,7 @@ public interface CassandraPersistentProperty
|
||||
|
||||
/**
|
||||
* The column's data type. Not valid for a composite primary key.
|
||||
*
|
||||
*
|
||||
* @return the Cassandra {@link DataType}
|
||||
* @throws InvalidDataAccessApiUsageException if the {@link DataType} cannot be resolved
|
||||
* @see CassandraType
|
||||
@@ -105,7 +106,7 @@ public interface CassandraPersistentProperty
|
||||
|
||||
/**
|
||||
* Whether the property is a partition key column or a cluster key column
|
||||
*
|
||||
*
|
||||
* @see #isPartitionKeyColumn()
|
||||
* @see #isClusterKeyColumn()
|
||||
*/
|
||||
@@ -116,7 +117,7 @@ public interface CassandraPersistentProperty
|
||||
|
||||
/**
|
||||
* Whether to force-quote the column names of this property.
|
||||
*
|
||||
*
|
||||
* @param forceQuote
|
||||
* @see CassandraPersistentProperty#getColumnNames()
|
||||
*/
|
||||
@@ -126,7 +127,7 @@ public interface CassandraPersistentProperty
|
||||
* If this property is mapped with a single column, set the column name to the given {@link CqlIdentifier}. If this
|
||||
* property is not mapped by a single column, throws {@link IllegalStateException}. If the given column name is null,
|
||||
* {@link IllegalArgumentException} is thrown.
|
||||
*
|
||||
*
|
||||
* @param columnName
|
||||
*/
|
||||
void setColumnName(CqlIdentifier columnName);
|
||||
@@ -134,18 +135,25 @@ public interface CassandraPersistentProperty
|
||||
/**
|
||||
* Sets this property's column names to the collection given. The given collection must have the same size as this
|
||||
* property's current list of column names, and must contain no <code>null</code> elements.
|
||||
*
|
||||
*
|
||||
* @param columnName
|
||||
*/
|
||||
void setColumnNames(List<CqlIdentifier> columnNames);
|
||||
|
||||
public enum PropertyToFieldNameConverter implements Converter<CassandraPersistentProperty, String> {
|
||||
/**
|
||||
* Returns whether the property is a {@link java.util.Map}.
|
||||
*
|
||||
* @return a boolean indicating whether this property type is a {@link java.util.Map}.
|
||||
*/
|
||||
boolean isMapLike();
|
||||
|
||||
enum PropertyToFieldNameConverter implements Converter<CassandraPersistentProperty, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(CassandraPersistentProperty source) {
|
||||
return source.getColumnName().toCql();
|
||||
public String convert(CassandraPersistentProperty property) {
|
||||
return property.getColumnName().toCql();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,27 +51,28 @@ import com.datastax.driver.core.Row;
|
||||
* Base class for {@link RepositoryQuery} implementations for Cassandra.
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
|
||||
protected static Logger log = LoggerFactory.getLogger(AbstractCassandraQuery.class);
|
||||
|
||||
private final CassandraQueryMethod method;
|
||||
private final CassandraQueryMethod queryMethod;
|
||||
private final CassandraOperations template;
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractCassandraQuery} from the given {@link CassandraQueryMethod} and
|
||||
* {@link CassandraOperations}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
*/
|
||||
public AbstractCassandraQuery(CassandraQueryMethod method, CassandraOperations operations) {
|
||||
public AbstractCassandraQuery(CassandraQueryMethod queryMethod, CassandraOperations operations) {
|
||||
|
||||
Assert.notNull(method, "CassandraQueryMethod must not be null");
|
||||
Assert.notNull(queryMethod, "CassandraQueryMethod must not be null");
|
||||
Assert.notNull(operations, "CassandraOperations must not be null");
|
||||
|
||||
this.method = method;
|
||||
this.queryMethod = queryMethod;
|
||||
this.template = operations;
|
||||
}
|
||||
|
||||
@@ -80,7 +81,7 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
*/
|
||||
@Override
|
||||
public CassandraQueryMethod getQueryMethod() {
|
||||
return method;
|
||||
return queryMethod;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -89,22 +90,23 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
CassandraParameterAccessor accessor = new ConvertingParameterAccessor(template.getConverter(),
|
||||
new CassandraParametersParameterAccessor(method, parameters));
|
||||
String query = createQuery(accessor);
|
||||
CassandraParameterAccessor parameterAccessor = new ConvertingParameterAccessor(template.getConverter(),
|
||||
new CassandraParametersParameterAccessor(queryMethod, parameters));
|
||||
|
||||
ResultProcessor processor = method.getResultProcessor().withDynamicProjection(accessor);
|
||||
String query = createQuery(parameterAccessor);
|
||||
|
||||
CassandraQueryExecution cassandraQueryExecution = getExecution(query, accessor,
|
||||
new ResultProcessingConverter(processor));
|
||||
ResultProcessor resultProcessor = queryMethod.getResultProcessor().withDynamicProjection(parameterAccessor);
|
||||
|
||||
CassandraReturnedType returnedType = new CassandraReturnedType(processor.getReturnedType(), template.getConverter().getCustomConversions());
|
||||
CassandraQueryExecution queryExecution = getExecution(query, parameterAccessor,
|
||||
new ResultProcessingConverter(resultProcessor));
|
||||
|
||||
if (returnedType.isProjecting()) {
|
||||
return cassandraQueryExecution.execute(query, returnedType.getDomainType());
|
||||
}
|
||||
CassandraReturnedType returnedType = new CassandraReturnedType(resultProcessor.getReturnedType(),
|
||||
template.getConverter().getCustomConversions());
|
||||
|
||||
return cassandraQueryExecution.execute(query, returnedType.getReturnedType());
|
||||
Class<?> resultType = (returnedType.isProjecting() ? returnedType.getDomainType()
|
||||
: returnedType.getReturnedType());
|
||||
|
||||
return queryExecution.execute(query, resultType);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -123,11 +125,11 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
private CassandraQueryExecution getExecutionToWrap(CassandraParameterAccessor accessor,
|
||||
Converter<Object, Object> resultProcessing) {
|
||||
|
||||
if (method.isCollectionQuery()) {
|
||||
if (queryMethod.isCollectionQuery()) {
|
||||
return new CollectionExecution(template);
|
||||
} else if (method.isResultSetQuery()) {
|
||||
} else if (queryMethod.isResultSetQuery()) {
|
||||
return new ResultSetQuery(template);
|
||||
} else if (method.isStreamQuery()) {
|
||||
} else if (queryMethod.isStreamQuery()) {
|
||||
return new StreamExecution(template, resultProcessing);
|
||||
} else {
|
||||
return new SingleEntityExecution(template);
|
||||
@@ -145,7 +147,7 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
public Object getCollectionOfEntity(ResultSet resultSet, Class<?> declaredReturnType,
|
||||
Class<?> returnedUnwrappedObjectType) {
|
||||
|
||||
Collection<Object> results = null;
|
||||
Collection<Object> results;
|
||||
|
||||
if (ClassUtils.isAssignable(SortedSet.class, declaredReturnType)) {
|
||||
results = new TreeSet<Object>();
|
||||
@@ -156,6 +158,7 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
}
|
||||
|
||||
CassandraConverter converter = template.getConverter();
|
||||
|
||||
for (Row row : resultSet) {
|
||||
results.add(converter.read(returnedUnwrappedObjectType, row));
|
||||
}
|
||||
@@ -171,45 +174,51 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
*/
|
||||
@Deprecated
|
||||
public Object getSingleEntity(ResultSet resultSet, Class<?> type) {
|
||||
if (resultSet.isExhausted()) {
|
||||
return null;
|
||||
|
||||
Object result = (resultSet.isExhausted() ? null : template.getConverter().read(type, resultSet.one()));
|
||||
|
||||
warnIfMoreResults(resultSet);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private void warnIfMoreResults(ResultSet resultSet) {
|
||||
if (log.isWarnEnabled() && !resultSet.isExhausted()) {
|
||||
int count = 0;
|
||||
|
||||
while (resultSet.one() != null) {
|
||||
count++;
|
||||
}
|
||||
|
||||
log.warn("ignoring extra {} row{}", count, count == 1 ? "" : "s");
|
||||
}
|
||||
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
Object object = template.getConverter().read(type, iterator.next());
|
||||
|
||||
warnIfMoreResults(iterator);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
protected void warnIfMoreResults(Iterator<Row> iterator) {
|
||||
if (log.isWarnEnabled() && iterator.hasNext()) {
|
||||
int count = 0;
|
||||
|
||||
int i = 0;
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
i++;
|
||||
for ( ; iterator.hasNext(); iterator.next()) {
|
||||
count++;
|
||||
}
|
||||
|
||||
log.warn("ignoring extra {} row{}", i, i == 1 ? "" : "s");
|
||||
log.warn("ignoring extra {} row{}", count, count == 1 ? "" : "s");
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ConversionService getConversionService() {
|
||||
return template.getConverter().getConversionService();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param conversionService
|
||||
* @deprecated {@link org.springframework.data.cassandra.mapping.CassandraMappingContext} handles type conversion.
|
||||
*/
|
||||
@Deprecated
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
throw new UnsupportedOperationException("setConversionService(ConversionService) is not supported anymore. "
|
||||
+ "Please use CassandraMappingContext instead");
|
||||
+ "Please use CassandraMappingContext instead");
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public ConversionService getConversionService() {
|
||||
return template.getConverter().getConversionService();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -229,37 +238,33 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
this.customConversions = customConversions;
|
||||
}
|
||||
|
||||
boolean isProjecting(){
|
||||
boolean isProjecting() {
|
||||
|
||||
if(!returnedType.isProjecting()){
|
||||
if (!returnedType.isProjecting()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Spring Data Cassandra allows List<Map<String, Object> and Map<String, Object> declarations on query methods
|
||||
// so we don't want to let projection kick in
|
||||
if(ClassUtils.isAssignable(Map.class, returnedType.getReturnedType())){
|
||||
// Spring Data Cassandra allows List<Map<String, Object> and Map<String, Object> declarations
|
||||
// on query methods so we don't want to let projection kick in
|
||||
if (ClassUtils.isAssignable(Map.class, returnedType.getReturnedType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Type conversion using registered conversions is handled on template level
|
||||
if(customConversions.hasCustomWriteTarget(returnedType.getReturnedType())){
|
||||
if (customConversions.hasCustomWriteTarget(returnedType.getReturnedType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Don't apply projection on Cassandra simple types
|
||||
if(customConversions.isSimpleType(returnedType.getReturnedType())){
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
Class<?> getReturnedType() {
|
||||
return returnedType.getReturnedType();
|
||||
return !customConversions.isSimpleType(returnedType.getReturnedType());
|
||||
}
|
||||
|
||||
Class<?> getDomainType() {
|
||||
return returnedType.getDomainType();
|
||||
}
|
||||
|
||||
Class<?> getReturnedType() {
|
||||
return returnedType.getReturnedType();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,13 +19,11 @@ import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
|
||||
import org.springframework.data.cassandra.mapping.CassandraType;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraParameters.CassandraParameter;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Custom extension of {@link Parameters} discovering additional properties of query method parameters.
|
||||
@@ -78,14 +76,11 @@ public class CassandraParameters extends Parameters<CassandraParameters, Cassand
|
||||
super(parameter);
|
||||
|
||||
if (parameter.hasParameterAnnotation(CassandraType.class)) {
|
||||
|
||||
CassandraType cassandraType = parameter.getParameterAnnotation(CassandraType.class);
|
||||
|
||||
if (cassandraType.type() == null) {
|
||||
throw new IllegalArgumentException(
|
||||
String.format("You must specify the type() when annotating method parameters with @%s",
|
||||
CassandraType.class.getSimpleName()));
|
||||
}
|
||||
Assert.notNull(cassandraType.type(), String.format(
|
||||
"You must specify the type() when annotating method parameters with @%s",
|
||||
CassandraType.class.getSimpleName()));
|
||||
|
||||
this.cassandraType = cassandraType;
|
||||
} else {
|
||||
@@ -95,7 +90,7 @@ public class CassandraParameters extends Parameters<CassandraParameters, Cassand
|
||||
|
||||
/**
|
||||
* Returns the {@link CassandraType} for the declared parameter if specified using {@link org.springframework.data.cassandra.mapping.CassandraType}.
|
||||
*
|
||||
*
|
||||
* @return the {@link CassandraType} or {@literal null}.
|
||||
*/
|
||||
public CassandraType getCassandraType() {
|
||||
|
||||
@@ -33,7 +33,7 @@ public class CassandraParametersParameterAccessor extends ParametersParameterAcc
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraParametersParameterAccessor}.
|
||||
*
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param values must not be {@literal null}.
|
||||
*/
|
||||
@@ -41,14 +41,16 @@ public class CassandraParametersParameterAccessor extends ParametersParameterAcc
|
||||
super(method.getParameters(), values);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.repository.query.CassandraParameterAccessor#findCassandraType(int)
|
||||
*/
|
||||
public CassandraType findCassandraType(int index) {
|
||||
return getParameters().getParameter(index).getCassandraType();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.repository.query.CassandraParameterAccessor#getDataType(int)
|
||||
*/
|
||||
@Override
|
||||
@@ -56,22 +58,12 @@ public class CassandraParametersParameterAccessor extends ParametersParameterAcc
|
||||
|
||||
CassandraType cassandraType = findCassandraType(index);
|
||||
|
||||
if (cassandraType != null) {
|
||||
return CassandraSimpleTypeHolder.getDataTypeFor(cassandraType.type());
|
||||
}
|
||||
|
||||
return CassandraSimpleTypeHolder.getDataTypeFor(getParameterType(index));
|
||||
return (cassandraType != null ? CassandraSimpleTypeHolder.getDataTypeFor(cassandraType.type())
|
||||
: CassandraSimpleTypeHolder.getDataTypeFor(getParameterType(index)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.repository.query.CassandraParameterAccessor#getParameterType(int)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getParameterType(int index) {
|
||||
return getParameters().getParameter(index).getType();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.ParametersParameterAccessor#getParameters()
|
||||
*/
|
||||
@Override
|
||||
@@ -79,4 +71,12 @@ public class CassandraParametersParameterAccessor extends ParametersParameterAcc
|
||||
return (CassandraParameters) super.getParameters();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.repository.query.CassandraParameterAccessor#getParameterType(int)
|
||||
*/
|
||||
@Override
|
||||
public Class<?> getParameterType(int index) {
|
||||
return getParameters().getParameter(index).getType();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
@@ -39,7 +38,6 @@ import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.datastax.driver.core.querybuilder.Clause;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
@@ -50,35 +48,39 @@ import com.datastax.driver.core.querybuilder.Select;
|
||||
*
|
||||
* @author Matthew Adams
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
|
||||
private static final Pattern PUNCTATION_PATTERN = Pattern.compile("\\p{Punct}");
|
||||
private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("\\p{Punct}");
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CassandraQueryCreator.class);
|
||||
private final CassandraMappingContext context;
|
||||
private final WhereBuilder whereBuilder = new WhereBuilder();
|
||||
|
||||
private final CassandraMappingContext mappingContext;
|
||||
|
||||
private final CassandraPersistentEntity<?> entity;
|
||||
|
||||
private final WhereBuilder whereBuilder = new WhereBuilder();
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor}
|
||||
* and {@link MappingContext}.
|
||||
*
|
||||
*
|
||||
* @param tree must not be {@literal null}.
|
||||
* @param accessor must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
* @param entityMetadata must not be {@literal null}.
|
||||
*/
|
||||
public CassandraQueryCreator(PartTree tree, CassandraParameterAccessor accessor, CassandraMappingContext context,
|
||||
EntityMetadata<?> entityMetadata) {
|
||||
public CassandraQueryCreator(PartTree tree, CassandraParameterAccessor accessor,
|
||||
CassandraMappingContext mappingContext, EntityMetadata<?> entityMetadata) {
|
||||
|
||||
super(tree, accessor);
|
||||
|
||||
Assert.notNull(context, "CassandraMappingContext must not be null");
|
||||
Assert.notNull(entityMetadata, "EntityInformation must not be null");
|
||||
Assert.notNull(mappingContext, "CassandraMappingContext must not be null");
|
||||
Assert.notNull(entityMetadata, "EntityMetaData must not be null");
|
||||
|
||||
this.context = context;
|
||||
this.entity = context.getPersistentEntity(entityMetadata.getJavaType());
|
||||
this.mappingContext = mappingContext;
|
||||
this.entity = mappingContext.getPersistentEntity(entityMetadata.getJavaType());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -87,8 +89,9 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
@Override
|
||||
protected Clause create(Part part, Iterator<Object> iterator) {
|
||||
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path = mappingContext.getPersistentPropertyPath(part.getProperty());
|
||||
CassandraPersistentProperty property = path.getLeafProperty();
|
||||
|
||||
return from(part, property, (PotentiallyConvertingIterator) iterator);
|
||||
}
|
||||
|
||||
@@ -103,18 +106,19 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
}
|
||||
|
||||
whereBuilder.and(base);
|
||||
|
||||
return create(part, iterator);
|
||||
}
|
||||
|
||||
/*
|
||||
* Cassandra does not support OR queries.
|
||||
*
|
||||
*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.parser.AbstractQueryCreator#or(java.lang.Object, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
protected Clause or(Clause base, Clause criteria) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Cassandra does not support an OR operator!"));
|
||||
throw new InvalidDataAccessApiUsageException("Cassandra does not support an OR operator");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -166,14 +170,18 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
case SIMPLE_PROPERTY:
|
||||
return QueryBuilder.eq(columnName(property), parameters.nextConverted(property));
|
||||
default:
|
||||
throw new InvalidDataAccessApiUsageException(
|
||||
String.format("Unsupported Keyword: [%s] in part [%s]", type, part));
|
||||
throw new InvalidDataAccessApiUsageException(String.format(
|
||||
"Unsupported keyword [%s] in part [%s]", type, part));
|
||||
}
|
||||
}
|
||||
|
||||
private static String columnName(CassandraPersistentProperty property) {
|
||||
return property.getColumnName().toCql();
|
||||
}
|
||||
|
||||
private Clause containing(CassandraPersistentProperty property, Object bindableValue) {
|
||||
|
||||
if (property.isCollectionLike() || ClassUtils.isAssignable(Map.class, property.getType())) {
|
||||
if (property.isCollectionLike() || property.isMapLike()) {
|
||||
return QueryBuilder.contains(columnName(property), bindableValue);
|
||||
}
|
||||
|
||||
@@ -182,32 +190,22 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
|
||||
private Object like(Type type, Object value) {
|
||||
|
||||
if (value == null) {
|
||||
return null;
|
||||
if (value != null) {
|
||||
switch (type) {
|
||||
case LIKE:
|
||||
return value;
|
||||
case CONTAINING:
|
||||
return "%" + value + "%";
|
||||
case STARTING_WITH:
|
||||
return value + "%";
|
||||
case ENDING_WITH:
|
||||
return "%" + value;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Part Type [%s] not supported with like queries", type));
|
||||
}
|
||||
|
||||
if (type == Type.LIKE) {
|
||||
return value;
|
||||
}
|
||||
|
||||
if (type == Type.CONTAINING) {
|
||||
return "%" + value + "%";
|
||||
}
|
||||
|
||||
if (type == Type.STARTING_WITH) {
|
||||
return value + "%";
|
||||
}
|
||||
|
||||
if (type == Type.ENDING_WITH) {
|
||||
return "%" + value;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Part Type [%s] not supported with like queries", type));
|
||||
|
||||
}
|
||||
|
||||
private static String columnName(CassandraPersistentProperty property) {
|
||||
return property.getColumnName().toCql();
|
||||
return null;
|
||||
}
|
||||
|
||||
private Object[] nextAsArray(CassandraPersistentProperty property, PotentiallyConvertingIterator iterator) {
|
||||
@@ -225,7 +223,7 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
|
||||
/**
|
||||
* Where clause builder. Collects {@link Clause clauses} and builds the where-clause depending on the WHERE type.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
static class WhereBuilder {
|
||||
@@ -233,16 +231,15 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
private List<Clause> clauses = new ArrayList<Clause>();
|
||||
|
||||
Clause and(Clause clause) {
|
||||
|
||||
clauses.add(clause);
|
||||
return clause;
|
||||
}
|
||||
|
||||
Select.Where build(Select.Where where) {
|
||||
|
||||
for (Clause clause : clauses) {
|
||||
where = where.and(clause);
|
||||
}
|
||||
|
||||
return where;
|
||||
}
|
||||
}
|
||||
@@ -255,19 +252,14 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
/**
|
||||
* Build a {@link Select} statement from the given {@link WhereBuilder} and {@link Sort}. Resolves property names
|
||||
* for {@link Sort} using the {@link CassandraPersistentEntity}.
|
||||
*
|
||||
* @param whereBuilder
|
||||
* @param entity
|
||||
* @param sort
|
||||
* @return
|
||||
*/
|
||||
static Select select(CassandraPersistentEntity<?> entity, WhereBuilder whereBuilder, Sort sort) {
|
||||
|
||||
Select select = QueryBuilder.select().from(entity.getTableName().toCql());
|
||||
|
||||
whereBuilder.build(select.where());
|
||||
|
||||
if (sort != null) {
|
||||
|
||||
for (Order order : sort) {
|
||||
|
||||
String dotPath = order.getProperty();
|
||||
@@ -287,7 +279,7 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
private static CassandraPersistentProperty getPersistentProperty(CassandraPersistentEntity<?> entity,
|
||||
String dotPath) {
|
||||
|
||||
String[] segments = PUNCTATION_PATTERN.split(dotPath);
|
||||
String[] segments = PUNCTUATION_PATTERN.split(dotPath);
|
||||
|
||||
CassandraPersistentProperty property = null;
|
||||
CassandraPersistentEntity<?> currentEntity = entity;
|
||||
@@ -301,12 +293,11 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
}
|
||||
|
||||
if (property != null) {
|
||||
|
||||
return property;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(
|
||||
String.format("Cannot resolve path [%s] to a property of [%s]", dotPath, entity.getName()));
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"Cannot resolve path [%s] to a property of [%s]", dotPath, entity.getName()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -40,29 +40,32 @@ import com.datastax.driver.core.ResultSet;
|
||||
* @author Matthew Adams
|
||||
* @author Oliver Gierke
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
public class CassandraQueryMethod extends QueryMethod {
|
||||
|
||||
private final Method method;
|
||||
private CassandraEntityMetadata<?> entityMetadata;
|
||||
|
||||
private final CassandraMappingContext mappingContext;
|
||||
private CassandraEntityMetadata<?> metadata;
|
||||
|
||||
private final Method method;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraQueryMethod} from the given {@link Method}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param metadata must not be {@literal null}.
|
||||
* @param repositoryMetadata must not be {@literal null}.
|
||||
* @param projectionFactory must not be {@literal null}.
|
||||
* @param mappingContext must not be {@literal null}.
|
||||
*/
|
||||
public CassandraQueryMethod(Method method, RepositoryMetadata metadata, ProjectionFactory factory,
|
||||
CassandraMappingContext mappingContext) {
|
||||
public CassandraQueryMethod(Method method, RepositoryMetadata repositoryMetadata,
|
||||
ProjectionFactory projectionFactory, CassandraMappingContext mappingContext) {
|
||||
|
||||
super(method, metadata, factory);
|
||||
super(method, repositoryMetadata, projectionFactory);
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null");
|
||||
|
||||
verify(method, metadata);
|
||||
verify(method, repositoryMetadata);
|
||||
|
||||
this.method = method;
|
||||
this.mappingContext = mappingContext;
|
||||
@@ -81,33 +84,34 @@ public class CassandraQueryMethod extends QueryMethod {
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public CassandraEntityMetadata<?> getEntityInformation() {
|
||||
|
||||
if (metadata == null) {
|
||||
|
||||
if (entityMetadata == null) {
|
||||
Class<?> returnedObjectType = getReturnedObjectType();
|
||||
Class<?> domainClass = getDomainClass();
|
||||
|
||||
if (ClassUtils.isPrimitiveOrWrapper(returnedObjectType)) {
|
||||
|
||||
this.metadata = new SimpleCassandraEntityMetadata<Object>((Class<Object>) domainClass,
|
||||
mappingContext.getPersistentEntity(domainClass));
|
||||
this.entityMetadata = new SimpleCassandraEntityMetadata<Object>((Class<Object>) domainClass,
|
||||
mappingContext.getPersistentEntity(domainClass));
|
||||
|
||||
} else {
|
||||
|
||||
CassandraPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
|
||||
CassandraPersistentEntity<?> managedEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
returnedEntity = returnedEntity == null || returnedEntity.getType().isInterface() ? managedEntity
|
||||
: returnedEntity;
|
||||
CassandraPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType)
|
||||
? returnedEntity : managedEntity;
|
||||
|
||||
this.metadata = new SimpleCassandraEntityMetadata<Object>((Class<Object>) returnedEntity.getType(),
|
||||
collectionEntity);
|
||||
returnedEntity = (returnedEntity == null || returnedEntity.getType().isInterface()
|
||||
? managedEntity : returnedEntity);
|
||||
|
||||
// TODO collectionEntity?
|
||||
CassandraPersistentEntity<?> collectionEntity = domainClass.isAssignableFrom(returnedObjectType)
|
||||
? returnedEntity : managedEntity;
|
||||
|
||||
this.entityMetadata = new SimpleCassandraEntityMetadata<Object>(
|
||||
(Class<Object>) returnedEntity.getType(), collectionEntity);
|
||||
}
|
||||
}
|
||||
|
||||
return this.metadata;
|
||||
return this.entityMetadata;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -132,9 +136,8 @@ public class CassandraQueryMethod extends QueryMethod {
|
||||
* @return
|
||||
*/
|
||||
public String getAnnotatedQuery() {
|
||||
|
||||
String query = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
return StringUtils.hasText(query) ? query : null;
|
||||
return (StringUtils.hasText(query) ? query : null);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -52,7 +52,6 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
private final CassandraParameterAccessor delegate;
|
||||
|
||||
ConvertingParameterAccessor(CassandraConverter cassandraConverter, CassandraParameterAccessor delegate) {
|
||||
|
||||
this.cassandraConverter = cassandraConverter;
|
||||
this.delegate = delegate;
|
||||
}
|
||||
@@ -102,11 +101,8 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
|
||||
DataType dataType = delegate.getDataType(index);
|
||||
|
||||
if (dataType != null) {
|
||||
return dataType;
|
||||
}
|
||||
|
||||
return cassandraConverter.getMappingContext().getDataType(getParameterType(index));
|
||||
return (dataType != null ? dataType
|
||||
: cassandraConverter.getMappingContext().getDataType(getParameterType(index)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -150,13 +146,14 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
&& property.isCollectionLike()) {
|
||||
|
||||
Class<?> customWriteTarget = getCustomConversions().getCustomWriteTarget(property.getActualType());
|
||||
|
||||
if (Collection.class.isAssignableFrom(property.getType()) && bindableValue instanceof Collection) {
|
||||
|
||||
Collection<Object> original = (Collection<Object>) bindableValue;
|
||||
Collection<Object> converted = CollectionFactory.createCollection(property.getType(), original.size());
|
||||
|
||||
for (Object o : original) {
|
||||
converted.add(getConversionService().convert(o, customWriteTarget));
|
||||
for (Object element : original) {
|
||||
converted.add(getConversionService().convert(element, customWriteTarget));
|
||||
}
|
||||
|
||||
return converted;
|
||||
@@ -181,12 +178,12 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
/**
|
||||
* Return the {@link DataType} based on annotated parameters with {@link CassandraType}, the
|
||||
* {@link CassandraPersistentProperty} type or the declared parameter type.
|
||||
*
|
||||
* @param index
|
||||
* @param cassandraPersistentProperty
|
||||
*
|
||||
* @param index index of parameter.
|
||||
* @param property {@link CassandraPersistentProperty}.
|
||||
* @return the {@link DataType}
|
||||
*/
|
||||
DataType getDataType(int index, CassandraPersistentProperty cassandraPersistentProperty) {
|
||||
DataType getDataType(int index, CassandraPersistentProperty property) {
|
||||
|
||||
CassandraType cassandraType = delegate.findCassandraType(index);
|
||||
|
||||
@@ -197,24 +194,24 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
CassandraMappingContext mappingContext = cassandraConverter.getMappingContext();
|
||||
TypeInformation<?> typeInformation = ClassTypeInformation.from(getParameterType(index));
|
||||
|
||||
if (cassandraPersistentProperty == null) {
|
||||
if (property == null) {
|
||||
return mappingContext.getDataType(typeInformation.getType());
|
||||
}
|
||||
|
||||
DataType dataType = mappingContext.getDataType(cassandraPersistentProperty);
|
||||
DataType dataType = mappingContext.getDataType(property);
|
||||
|
||||
if (cassandraPersistentProperty.isCollectionLike() && !typeInformation.isCollectionLike()) {
|
||||
if (property.isCollectionLike() && !typeInformation.isCollectionLike()) {
|
||||
|
||||
if (dataType instanceof CollectionType) {
|
||||
|
||||
CollectionType collectionType = (CollectionType) dataType;
|
||||
|
||||
if (collectionType.getTypeArguments().size() == 1) {
|
||||
return collectionType.getTypeArguments().get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!cassandraPersistentProperty.isCollectionLike() && typeInformation.isCollectionLike()) {
|
||||
if (!property.isCollectionLike() && typeInformation.isCollectionLike()) {
|
||||
|
||||
if (typeInformation.isAssignableFrom(SET)) {
|
||||
return DataType.set(dataType);
|
||||
@@ -223,18 +220,18 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
return DataType.list(dataType);
|
||||
}
|
||||
|
||||
if (cassandraPersistentProperty.isMap()) {
|
||||
if (property.isMap()) {
|
||||
|
||||
if (dataType instanceof CollectionType) {
|
||||
|
||||
CollectionType collectionType = (CollectionType) dataType;
|
||||
|
||||
if (collectionType.getTypeArguments().size() == 2) {
|
||||
return collectionType.getTypeArguments().get(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return mappingContext.getDataType(cassandraPersistentProperty);
|
||||
return mappingContext.getDataType(property);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -299,5 +296,6 @@ class ConvertingParameterAccessor implements CassandraParameterAccessor {
|
||||
* @return the converted object, may be {@literal null}.
|
||||
*/
|
||||
Object nextConverted(CassandraPersistentProperty property);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,32 +24,33 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
* {@link RepositoryQuery} implementation for Cassandra.
|
||||
*
|
||||
*
|
||||
* @author Matthew Adams
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class PartTreeCassandraQuery extends AbstractCassandraQuery {
|
||||
|
||||
private final CassandraMappingContext mappingContext;
|
||||
|
||||
private final PartTree tree;
|
||||
private final CassandraMappingContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeCassandraQuery} from the given {@link QueryMethod} and {@link CassandraTemplate}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
*
|
||||
* @param queryMethod must not be {@literal null}.
|
||||
* @param operations must not be {@literal null}.
|
||||
*/
|
||||
public PartTreeCassandraQuery(CassandraQueryMethod method, CassandraOperations operations) {
|
||||
public PartTreeCassandraQuery(CassandraQueryMethod queryMethod, CassandraOperations operations) {
|
||||
|
||||
super(method, operations);
|
||||
super(queryMethod, operations);
|
||||
|
||||
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
|
||||
this.context = operations.getConverter().getMappingContext();
|
||||
this.tree = new PartTree(queryMethod.getName(), queryMethod.getEntityInformation().getJavaType());
|
||||
this.mappingContext = operations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link PartTree} backing the query.
|
||||
*
|
||||
*
|
||||
* @return the tree
|
||||
*/
|
||||
public PartTree getTree() {
|
||||
@@ -61,10 +62,11 @@ public class PartTreeCassandraQuery extends AbstractCassandraQuery {
|
||||
* @see org.springframework.data.cassandra.repository.query.AbstractCassandraQuery#createQuery(org.springframework.data.cassandra.repository.query.CassandraParameterAccessor, boolean)
|
||||
*/
|
||||
@Override
|
||||
protected String createQuery(CassandraParameterAccessor accessor) {
|
||||
protected String createQuery(CassandraParameterAccessor parameterAccessor) {
|
||||
|
||||
CassandraQueryCreator creator = new CassandraQueryCreator(tree, accessor, context,
|
||||
CassandraQueryCreator queryCreator = new CassandraQueryCreator(tree, parameterAccessor, mappingContext,
|
||||
getQueryMethod().getEntityInformation());
|
||||
return creator.createQuery().toString();
|
||||
|
||||
return queryCreator.createQuery().toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,29 +21,30 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Implementation of {@link CassandraEntityMetadata} based on the type and {@link CassandraPersistentEntity}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @since 1.5
|
||||
*/
|
||||
class SimpleCassandraEntityMetadata<T> implements CassandraEntityMetadata<T> {
|
||||
|
||||
private final CassandraPersistentEntity<?> entity;
|
||||
|
||||
private final Class<T> type;
|
||||
private final CassandraPersistentEntity<?> tableEntity;
|
||||
|
||||
/**
|
||||
* Creates a new {@link SimpleCassandraEntityMetadata} using the given type and {@link CassandraPersistentEntity} to
|
||||
* use for table lookups.
|
||||
*
|
||||
* @param type must not be {@literal null}.
|
||||
* @param tableEntity must not be {@literal null} or empty.
|
||||
* @param entity must not be {@literal null} or empty.
|
||||
*/
|
||||
public SimpleCassandraEntityMetadata(Class<T> type, CassandraPersistentEntity<?> tableEntity) {
|
||||
public SimpleCassandraEntityMetadata(Class<T> type, CassandraPersistentEntity<?> entity) {
|
||||
|
||||
Assert.notNull(type, "Type must not be null!");
|
||||
Assert.notNull(tableEntity, "Collection entity must not be null or empty!");
|
||||
Assert.notNull(type, "Type must not be null");
|
||||
Assert.notNull(entity, "Collection entity must not be null or empty");
|
||||
|
||||
this.type = type;
|
||||
this.tableEntity = tableEntity;
|
||||
this.entity = entity;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -51,7 +52,7 @@ class SimpleCassandraEntityMetadata<T> implements CassandraEntityMetadata<T> {
|
||||
*/
|
||||
@Override
|
||||
public CqlIdentifier getTableName() {
|
||||
return tableEntity.getTableName();
|
||||
return entity.getTableName();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2013-2016 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -32,6 +32,7 @@ import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryInformation;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.EvaluationContextProvider;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
@@ -39,11 +40,12 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Factory to create {@link TypedIdCassandraRepository} instances.
|
||||
*
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
* @author Thomas Darimont
|
||||
* @author Mark Paluch
|
||||
* @author John Blum
|
||||
*/
|
||||
public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
@@ -52,7 +54,7 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraRepositoryFactory} with the given {@link CassandraOperations}.
|
||||
*
|
||||
*
|
||||
* @param cassandraOperations must not be {@literal null}
|
||||
*/
|
||||
public CassandraRepositoryFactory(CassandraOperations cassandraOperations) {
|
||||
@@ -63,7 +65,8 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
this.mappingContext = cassandraOperations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getRepositoryBaseClass(org.springframework.data.repository.core.RepositoryMetadata)
|
||||
*/
|
||||
@Override
|
||||
@@ -71,7 +74,8 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
return SimpleCassandraRepository.class;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getTargetRepository(org.springframework.data.repository.core.RepositoryInformation)
|
||||
*/
|
||||
@Override
|
||||
@@ -81,7 +85,8 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
return getTargetRepositoryViaReflection(information, entityInformation, cassandraOperations);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getEntityInformation(java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
@@ -99,17 +104,27 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
cassandraOperations.getConverter());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(org.springframework.data.repository.query.QueryLookupStrategy.Key)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(Key)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
return getQueryLookupStrategy(key, null);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactorySupport#getQueryLookupStrategy(Key, EvaluationContextProvider)
|
||||
*/
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key, EvaluationContextProvider evaluationContextProvider) {
|
||||
return new CassandraQueryLookupStrategy();
|
||||
}
|
||||
|
||||
private class CassandraQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.repository.query.QueryLookupStrategy#resolveQuery(java.lang.reflect.Method, org.springframework.data.repository.core.RepositoryMetadata, org.springframework.data.projection.ProjectionFactory, org.springframework.data.repository.core.NamedQueries)
|
||||
*/
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
/*
|
||||
* Copyright 2013-2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@@ -26,11 +26,15 @@ import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* {@link org.springframework.beans.factory.FactoryBean} to create {@link TypedIdCassandraRepository} instances.
|
||||
*
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author John Blum
|
||||
* @see java.io.Serializable
|
||||
* @see org.springframework.data.repository.Repository
|
||||
* @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport
|
||||
*/
|
||||
public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable> extends
|
||||
RepositoryFactoryBeanSupport<T, S, ID> {
|
||||
public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extends Serializable>
|
||||
extends RepositoryFactoryBeanSupport<T, S, ID> {
|
||||
|
||||
private CassandraTemplate cassandraTemplate;
|
||||
|
||||
@@ -40,9 +44,10 @@ public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID e
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the {@link CassandraTemplate} to be used.
|
||||
*
|
||||
* @param operations the operations to set
|
||||
* Configures the {@link CassandraTemplate} used for Cassandra data access operations.
|
||||
*
|
||||
* @param cassandraTemplate {@link CassandraTemplate} used to perform CRUD, Query and general data access operations
|
||||
* on Apache Cassandra.
|
||||
*/
|
||||
public void setCassandraTemplate(CassandraTemplate cassandraTemplate) {
|
||||
this.cassandraTemplate = cassandraTemplate;
|
||||
@@ -51,7 +56,7 @@ public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID e
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
*
|
||||
* @see
|
||||
* org.springframework.data.repository.support.RepositoryFactoryBeanSupport
|
||||
* #afterPropertiesSet()
|
||||
@@ -59,7 +64,6 @@ public class CassandraRepositoryFactoryBean<T extends Repository<S, ID>, S, ID e
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
Assert.notNull(cassandraTemplate, "cassandraTemplate must not be null!");
|
||||
Assert.notNull(cassandraTemplate, "CassandraTemplate must not be null!");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -27,7 +27,6 @@ import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.cassandra.domain.Person;
|
||||
import org.springframework.data.cassandra.mapping.CassandraType;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.DataType.Name;
|
||||
|
||||
/**
|
||||
@@ -44,7 +43,7 @@ public class CassandraParametersUnitTests {
|
||||
* @see DATACASS-296
|
||||
*/
|
||||
@Test
|
||||
public void shouldUnknownDataTypeForSimpleType() throws Exception {
|
||||
public void shouldReturnUnknownDataTypeForSimpleType() throws Exception {
|
||||
|
||||
Method method = PersonRepository.class.getMethod("findByFirstname", String.class);
|
||||
CassandraParameters cassandraParameters = new CassandraParameters(method);
|
||||
|
||||
@@ -47,26 +47,25 @@ import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CassandraQueryCreator}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
* @soundtrack Odyssey - Everybody Move 9Club Mix
|
||||
*/
|
||||
public class CassandraQueryCreatorUnitTests {
|
||||
|
||||
CassandraMappingContext context;
|
||||
CassandraConverter converter;
|
||||
|
||||
@Rule public ExpectedException expection = ExpectedException.none();
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Before
|
||||
public void setUp() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
context = new BasicCassandraMappingContext();
|
||||
converter = new MappingCassandraConverter(context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsQueryCorrectly() {
|
||||
@@ -77,7 +76,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsQueryWithSortCorrectly() {
|
||||
@@ -88,7 +87,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsAndQueryCorrectly() {
|
||||
@@ -99,15 +98,15 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void rejectsNegatingQueryQuery() {
|
||||
public void rejectsNegatingQuery() {
|
||||
createQuery("findByFirstnameNot", Person.class, "Walter");
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test(expected = InvalidDataAccessApiUsageException.class)
|
||||
public void rejectsOrQuery() {
|
||||
@@ -115,7 +114,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsGreaterThanQueryCorrectly() {
|
||||
@@ -126,7 +125,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsGreaterThanEqualQueryCorrectly() {
|
||||
@@ -137,7 +136,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsLessThanQueryCorrectly() {
|
||||
@@ -148,7 +147,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsLessThanEqualQueryCorrectly() {
|
||||
@@ -159,7 +158,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsInQueryCorrectly() {
|
||||
@@ -170,7 +169,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsInQueryWithListCorrectly() {
|
||||
@@ -181,30 +180,32 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsInQueryWithArrayCorrectly() {
|
||||
|
||||
String query = createQuery("findByFirstnameInAndLastname", Person.class, new String[] { "Walter", "Gus" }, "Fring");
|
||||
String query = createQuery("findByFirstnameInAndLastname", Person.class,
|
||||
new String[] { "Walter", "Gus" }, "Fring");
|
||||
|
||||
assertThat(query, is(equalTo("SELECT * FROM person WHERE firstname IN ('Walter','Gus') AND lastname='Fring';")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsLikeQueryCorrectly() {
|
||||
|
||||
assertThat(createQuery("findByFirstnameLike", Person.class, "Wal%ter"),
|
||||
is(equalTo("SELECT * FROM person WHERE firstname LIKE 'Wal%ter';")));
|
||||
|
||||
assertThat(createQuery("findByFirstnameLike", Person.class, "Walter"),
|
||||
is(equalTo("SELECT * FROM person WHERE firstname LIKE 'Walter';")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsStartsWithQueryCorrectly() {
|
||||
@@ -215,7 +216,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsEndsWithQueryCorrectly() {
|
||||
@@ -226,7 +227,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsContainsQueryOnSimplePropertyCorrectly() {
|
||||
@@ -237,7 +238,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsContainsQueryOnSetPropertyCorrectly() {
|
||||
@@ -248,7 +249,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsContainsQueryOnListPropertyCorrectly() {
|
||||
@@ -259,7 +260,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsContainsQueryOnMapPropertyCorrectly() {
|
||||
@@ -270,7 +271,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsIsTrueQueryCorrectly() {
|
||||
@@ -281,7 +282,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsIsFalseQueryCorrectly() {
|
||||
@@ -292,7 +293,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsQueryUsingQuotingCorrectly() {
|
||||
@@ -303,7 +304,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsFindByPrimaryKeyPartCorrectly() {
|
||||
@@ -314,7 +315,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsFindByPrimaryKeyPartWithSortCorrectly() {
|
||||
@@ -325,7 +326,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void createsFindByPrimaryKeyPartOfPrimaryKeyClassCorrectly() {
|
||||
@@ -337,7 +338,7 @@ public class CassandraQueryCreatorUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test(expected = IllegalStateException.class)
|
||||
public void createsFindByPrimaryKey2PartCorrectly() {
|
||||
|
||||
@@ -33,7 +33,7 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CassandraQueryMethod}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
public class CassandraQueryMethodUnitTests {
|
||||
@@ -46,7 +46,7 @@ public class CassandraQueryMethodUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void detectsCollectionFromRepoTypeIfReturnTypeNotAssignable() throws Exception {
|
||||
@@ -59,7 +59,7 @@ public class CassandraQueryMethodUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test(expected = IllegalArgumentException.class)
|
||||
public void rejectsNullMappingContext() throws Exception {
|
||||
@@ -71,7 +71,7 @@ public class CassandraQueryMethodUnitTests {
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void considersMethodAsCollectionQuery() throws Exception {
|
||||
@@ -88,8 +88,10 @@ public class CassandraQueryMethodUnitTests {
|
||||
return new CassandraQueryMethod(method, new DefaultRepositoryMetadata(repository), factory, context);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
interface SampleRepository extends Repository<Person, Long> {
|
||||
|
||||
List<Person> method();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
@@ -40,127 +39,127 @@ import com.datastax.driver.core.DataType;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link ConvertingParameterAccessor}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@SuppressWarnings("Since15")
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class ConvertingParameterAccessorUnitTests {
|
||||
|
||||
@Mock CassandraParameterAccessor delegateMock;
|
||||
@Mock CassandraPersistentProperty propertyMock;
|
||||
@Mock
|
||||
private CassandraParameterAccessor mockParameterAccessor;
|
||||
|
||||
@Mock
|
||||
private CassandraPersistentProperty mockProperty;
|
||||
|
||||
ConvertingParameterAccessor convertingParameterAccessor;
|
||||
|
||||
MappingCassandraConverter converter;
|
||||
ConvertingParameterAccessor accessor;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
this.converter = new MappingCassandraConverter(new BasicCassandraMappingContext());
|
||||
this.converter.afterPropertiesSet();
|
||||
this.accessor = new ConvertingParameterAccessor(converter, delegateMock);
|
||||
this.convertingParameterAccessor = new ConvertingParameterAccessor(converter, mockParameterAccessor);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-296
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-296">DATACASS-296</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnNullBindableValue() {
|
||||
assertThat(accessor.getBindableValue(0), is(nullValue()));
|
||||
assertThat(convertingParameterAccessor.getBindableValue(0), is(nullValue()));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-296
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-296">DATACASS-296</a>
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void shouldReturnNativeBindableValue() {
|
||||
when(mockParameterAccessor.getBindableValue(0)).thenReturn("hello");
|
||||
when(mockParameterAccessor.getDataType(0)).thenReturn(DataType.varchar());
|
||||
when(mockParameterAccessor.getParameterType(0)).thenReturn((Class) String.class);
|
||||
|
||||
when(delegateMock.getBindableValue(0)).thenReturn("hello");
|
||||
when(delegateMock.getDataType(0)).thenReturn(DataType.varchar());
|
||||
when(delegateMock.getParameterType(0)).thenReturn((Class) String.class);
|
||||
|
||||
assertThat(accessor.getBindableValue(0), is(equalTo((Object) "hello")));
|
||||
assertThat(convertingParameterAccessor.getBindableValue(0), is(equalTo((Object) "hello")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-296
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-296">DATACASS-296</a>
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void shouldReturnConvertedBindableValue() {
|
||||
|
||||
LocalDate localDate = LocalDate.of(2010, 7, 4);
|
||||
|
||||
when(delegateMock.getBindableValue(0)).thenReturn(localDate);
|
||||
when(delegateMock.getParameterType(0)).thenReturn((Class) LocalDate.class);
|
||||
when(mockParameterAccessor.getBindableValue(0)).thenReturn(localDate);
|
||||
when(mockParameterAccessor.getParameterType(0)).thenReturn((Class) LocalDate.class);
|
||||
|
||||
assertThat(accessor.getBindableValue(0),
|
||||
is(equalTo((Object) com.datastax.driver.core.LocalDate.fromYearMonthDay(2010, 7, 4))));
|
||||
assertThat(convertingParameterAccessor.getBindableValue(0),
|
||||
is(equalTo((Object) com.datastax.driver.core.LocalDate.fromYearMonthDay(2010, 7, 4))));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-296
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-296">DATACASS-296</a>
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldReturnDataTypeProvidedByDelegate() {
|
||||
when(mockParameterAccessor.getDataType(0)).thenReturn(DataType.varchar());
|
||||
|
||||
when(delegateMock.getDataType(0)).thenReturn(DataType.varchar());
|
||||
|
||||
assertThat(accessor.getDataType(0), is(equalTo(DataType.varchar())));
|
||||
assertThat(convertingParameterAccessor.getDataType(0), is(equalTo(DataType.varchar())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-296
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-296">DATACASS-296</a>
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void shouldConvertCollections() {
|
||||
|
||||
LocalDate localDate = LocalDate.of(2010, 7, 4);
|
||||
|
||||
when(delegateMock.iterator()).thenReturn((Iterator) Arrays.asList(Collections.singletonList(localDate)).iterator());
|
||||
when(delegateMock.getDataType(0)).thenReturn(DataType.list(DataType.date()));
|
||||
when(delegateMock.getParameterType(0)).thenReturn((Class) List.class);
|
||||
when(propertyMock.getType()).thenReturn((Class) List.class);
|
||||
when(propertyMock.getActualType()).thenReturn((Class) LocalDate.class);
|
||||
when(propertyMock.isCollectionLike()).thenReturn(true);
|
||||
when(mockParameterAccessor.iterator()).thenReturn((Iterator)
|
||||
Collections.singletonList(Collections.singletonList(localDate)).iterator());
|
||||
when(mockParameterAccessor.getDataType(0)).thenReturn(DataType.list(DataType.date()));
|
||||
when(mockParameterAccessor.getParameterType(0)).thenReturn((Class) List.class);
|
||||
when(mockProperty.getType()).thenReturn((Class) List.class);
|
||||
when(mockProperty.getActualType()).thenReturn((Class) LocalDate.class);
|
||||
when(mockProperty.isCollectionLike()).thenReturn(true);
|
||||
|
||||
PotentiallyConvertingIterator iterator = (PotentiallyConvertingIterator) accessor.iterator();
|
||||
Object converted = iterator.nextConverted(propertyMock);
|
||||
PotentiallyConvertingIterator iterator = (PotentiallyConvertingIterator) convertingParameterAccessor.iterator();
|
||||
Object converted = iterator.nextConverted(mockProperty);
|
||||
|
||||
assertThat(converted, is(instanceOf(List.class)));
|
||||
|
||||
List<?> list = (List<?>) converted;
|
||||
|
||||
assertThat(list.get(0), is(instanceOf(com.datastax.driver.core.LocalDate.class)));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings({"rawtypes", "unchecked"})
|
||||
public void shouldProvideTypeBasedOnValue() {
|
||||
when(mockParameterAccessor.getDataType(0)).thenReturn(null);
|
||||
when(mockParameterAccessor.getParameterType(0)).thenReturn((Class) LocalDate.class);
|
||||
|
||||
when(delegateMock.getDataType(0)).thenReturn(null);
|
||||
when(delegateMock.getParameterType(0)).thenReturn((Class) LocalDate.class);
|
||||
|
||||
assertThat(accessor.getDataType(0), is(equalTo(DataType.date())));
|
||||
assertThat(convertingParameterAccessor.getDataType(0), is(equalTo(DataType.date())));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
@SuppressWarnings("rawtypes")
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public void shouldProvideTypeBasedOnPropertyType() {
|
||||
when(mockProperty.getDataType()).thenReturn(DataType.varchar());
|
||||
when(mockProperty.findAnnotation(CassandraType.class)).thenReturn(mock(CassandraType.class));
|
||||
when(mockParameterAccessor.getParameterType(0)).thenReturn((Class) String.class);
|
||||
when(mockParameterAccessor.getDataType(0)).thenReturn(null);
|
||||
|
||||
when(propertyMock.getDataType()).thenReturn(DataType.varchar());
|
||||
when(propertyMock.findAnnotation(CassandraType.class)).thenReturn(mock(CassandraType.class));
|
||||
when(delegateMock.getParameterType(0)).thenReturn((Class) String.class);
|
||||
when(delegateMock.getDataType(0)).thenReturn(null);
|
||||
|
||||
assertThat(accessor.getDataType(0, propertyMock), is(equalTo(DataType.varchar())));
|
||||
assertThat(convertingParameterAccessor.getDataType(0, mockProperty), is(equalTo(DataType.varchar())));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,8 +16,8 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import static org.hamcrest.Matchers.*;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
import static org.junit.Assert.*;
|
||||
import static org.mockito.Mockito.*;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
@@ -42,66 +42,64 @@ import org.springframework.data.repository.core.support.DefaultRepositoryMetadat
|
||||
|
||||
/**
|
||||
* Unit tests for {@link PartTreeCassandraQuery}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class PartTreeCassandraQueryUnitTests {
|
||||
|
||||
public @Rule ExpectedException exception = ExpectedException.none();
|
||||
@Rule
|
||||
public ExpectedException exception = ExpectedException.none();
|
||||
|
||||
@Mock CassandraOperations cassandraOperationsMock;
|
||||
@Mock
|
||||
private CassandraOperations mockCassandraOperations;
|
||||
|
||||
CassandraMappingContext mappingContext;
|
||||
CassandraConverter converter;
|
||||
private CassandraMappingContext mappingContext;
|
||||
private CassandraConverter converter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
mappingContext = new BasicCassandraMappingContext();
|
||||
converter = new MappingCassandraConverter(mappingContext);
|
||||
when(cassandraOperationsMock.getConverter()).thenReturn(converter);
|
||||
|
||||
when(mockCassandraOperations.getConverter()).thenReturn(converter);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldDeriveSimpleQuery() {
|
||||
|
||||
String query = deriveQueryFromMethod("findByLastname", "foo");
|
||||
|
||||
assertThat(query, is(equalTo("SELECT * FROM person WHERE lastname='foo';")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldDeriveSimpleQueryWithoutNames() {
|
||||
|
||||
String query = deriveQueryFromMethod("findPersonBy");
|
||||
|
||||
assertThat(query, is(equalTo("SELECT * FROM person;")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldDeriveAndQuery() {
|
||||
|
||||
String query = deriveQueryFromMethod("findByFirstnameAndLastname", "foo", "bar" );
|
||||
|
||||
assertThat(query, is(equalTo("SELECT * FROM person WHERE firstname='foo' AND lastname='bar';")));
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void usesDynamicProjection() {
|
||||
|
||||
String query = deriveQueryFromMethod("findDynamicallyProjectedBy", PersonProjection.class);
|
||||
|
||||
assertThat(query, is(equalTo("SELECT * FROM person;")));
|
||||
@@ -109,7 +107,6 @@ public class PartTreeCassandraQueryUnitTests {
|
||||
|
||||
|
||||
private String deriveQueryFromMethod(String method, Object... args) {
|
||||
|
||||
Class<?>[] types = new Class<?>[args.length];
|
||||
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
@@ -119,19 +116,18 @@ public class PartTreeCassandraQueryUnitTests {
|
||||
PartTreeCassandraQuery partTreeQuery = createQueryForMethod(method, types);
|
||||
|
||||
CassandraParameterAccessor accessor = new CassandraParametersParameterAccessor(partTreeQuery.getQueryMethod(), args);
|
||||
return partTreeQuery.createQuery(new ConvertingParameterAccessor(cassandraOperationsMock.getConverter(), accessor));
|
||||
|
||||
return partTreeQuery.createQuery(new ConvertingParameterAccessor(mockCassandraOperations.getConverter(), accessor));
|
||||
}
|
||||
|
||||
private PartTreeCassandraQuery createQueryForMethod(String methodName, Class<?>... paramTypes) {
|
||||
|
||||
try {
|
||||
|
||||
Method method = Repo.class.getMethod(methodName, paramTypes);
|
||||
ProjectionFactory factory = new SpelAwareProxyProjectionFactory();
|
||||
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method, new DefaultRepositoryMetadata(Repo.class), factory,
|
||||
mappingContext);
|
||||
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method,
|
||||
new DefaultRepositoryMetadata(Repo.class), factory, mappingContext);
|
||||
|
||||
return new PartTreeCassandraQuery(queryMethod, cassandraOperationsMock);
|
||||
return new PartTreeCassandraQuery(queryMethod, mockCassandraOperations);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new IllegalArgumentException(e.getMessage(), e);
|
||||
} catch (SecurityException e) {
|
||||
|
||||
@@ -36,21 +36,27 @@ import org.springframework.data.repository.Repository;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link CassandraRepositoryFactory}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
public class CassandraRepositoryFactoryUnitTests {
|
||||
|
||||
@Mock CassandraTemplate template;
|
||||
@Mock CassandraConverter converter;
|
||||
@Mock CassandraMappingContext mappingContext;
|
||||
@Mock CassandraPersistentEntity entity;
|
||||
@Mock
|
||||
private CassandraConverter converter;
|
||||
|
||||
@Mock
|
||||
private CassandraMappingContext mappingContext;
|
||||
|
||||
@Mock
|
||||
private CassandraPersistentEntity entity;
|
||||
|
||||
@Mock
|
||||
private CassandraTemplate template;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
when(template.getConverter()).thenReturn(converter);
|
||||
when(converter.getMappingContext()).thenReturn(mappingContext);
|
||||
}
|
||||
@@ -60,12 +66,14 @@ public class CassandraRepositoryFactoryUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void usesMappingCassandraEntityInformationIfMappingContextSet() {
|
||||
|
||||
when(mappingContext.getPersistentEntity(Person.class)).thenReturn(entity);
|
||||
when(entity.getType()).thenReturn(Person.class);
|
||||
|
||||
CassandraRepositoryFactory factory = new CassandraRepositoryFactory(template);
|
||||
CassandraEntityInformation<Person, Serializable> entityInformation = factory.getEntityInformation(Person.class);
|
||||
CassandraRepositoryFactory repositoryFactory = new CassandraRepositoryFactory(template);
|
||||
|
||||
CassandraEntityInformation<Person, Serializable> entityInformation =
|
||||
repositoryFactory.getEntityInformation(Person.class);
|
||||
|
||||
assertTrue(entityInformation instanceof MappingCassandraEntityInformation);
|
||||
}
|
||||
|
||||
@@ -74,16 +82,15 @@ public class CassandraRepositoryFactoryUnitTests {
|
||||
*/
|
||||
@Test
|
||||
public void createsRepositoryWithIdTypeLong() {
|
||||
|
||||
when(mappingContext.getPersistentEntity(Person.class)).thenReturn(entity);
|
||||
when(entity.getType()).thenReturn(Person.class);
|
||||
|
||||
CassandraRepositoryFactory factory = new CassandraRepositoryFactory(template);
|
||||
MyPersonRepository repository = factory.getRepository(MyPersonRepository.class);
|
||||
CassandraRepositoryFactory repositoryFactory = new CassandraRepositoryFactory(template);
|
||||
MyPersonRepository repository = repositoryFactory.getRepository(MyPersonRepository.class);
|
||||
|
||||
assertThat(repository, is(notNullValue()));
|
||||
}
|
||||
|
||||
interface MyPersonRepository extends Repository<Person, Long> {
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -45,11 +45,12 @@ import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Integration tests for query derivation through {@link PersonRepository}.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
@SuppressWarnings("all")
|
||||
public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
|
||||
|
||||
@Configuration
|
||||
@@ -68,14 +69,18 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
|
||||
}
|
||||
|
||||
@Autowired CassandraOperations template;
|
||||
@Autowired PersonRepository personRepository;
|
||||
@Autowired
|
||||
private CassandraOperations template;
|
||||
|
||||
Person walter, skyler, flynn;
|
||||
@Autowired
|
||||
private PersonRepository personRepository;
|
||||
|
||||
private Person walter;
|
||||
private Person skyler;
|
||||
private Person flynn;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
|
||||
deleteAllEntities();
|
||||
|
||||
Person person = new Person("Walter", "White");
|
||||
@@ -87,7 +92,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByLastname() {
|
||||
@@ -98,7 +103,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByLastnameAndDynamicSort() {
|
||||
@@ -109,7 +114,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByLastnameWithOrdering() {
|
||||
@@ -120,7 +125,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByFirstnameAndLastname() {
|
||||
@@ -131,7 +136,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void executesCollectionQueryWithProjectionCorrectly() {
|
||||
@@ -146,7 +151,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByNumberOfChildren() throws Exception {
|
||||
@@ -154,6 +159,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
assumeThat(SpringVersion.getVersion(), startsWith("4.3"));
|
||||
|
||||
template.execute("CREATE INDEX IF NOT EXISTS person_number_of_children ON person (numberofchildren);");
|
||||
|
||||
// Give Cassandra some time to build the index
|
||||
Thread.sleep(500);
|
||||
|
||||
@@ -163,12 +169,13 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldFindByLocalDate() throws InterruptedException {
|
||||
|
||||
template.execute("CREATE INDEX IF NOT EXISTS person_created_date ON person (createddate);");
|
||||
|
||||
// Give Cassandra some time to build the index
|
||||
Thread.sleep(500);
|
||||
|
||||
@@ -181,12 +188,13 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseQueryOverride() {
|
||||
|
||||
Person otherWalter = new Person("Walter", "Black");
|
||||
|
||||
personRepository.save(otherWalter);
|
||||
|
||||
List<Person> result = personRepository.findByFirstname("Walter");
|
||||
@@ -195,16 +203,16 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseStartsWithQuery() throws InterruptedException {
|
||||
|
||||
Version version = CassandraVersion.get(template.getSession());
|
||||
assumeTrue(version.isGreaterThanOrEqualTo(Version.parse("3.4")));
|
||||
assumeTrue(CassandraVersion.get(template.getSession()).isGreaterThanOrEqualTo(Version.parse("3.4")));
|
||||
|
||||
template.execute(
|
||||
"CREATE CUSTOM INDEX IF NOT EXISTS fn_starts_with ON person (nickname) USING 'org.apache.cassandra.index.sasi.SASIIndex';");
|
||||
|
||||
// Give Cassandra some time to build the index
|
||||
Thread.sleep(500);
|
||||
|
||||
@@ -215,17 +223,17 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
}
|
||||
|
||||
/**
|
||||
* @see DATACASS-7
|
||||
* @see <a href="https://jira.spring.io/browse/DATACASS-7">DATACASS-7</a>
|
||||
*/
|
||||
@Test
|
||||
public void shouldUseContainsQuery() throws InterruptedException {
|
||||
|
||||
Version version = CassandraVersion.get(template.getSession());
|
||||
assumeTrue(version.isGreaterThanOrEqualTo(Version.parse("3.4")));
|
||||
assumeTrue(CassandraVersion.get(template.getSession()).isGreaterThanOrEqualTo(Version.parse("3.4")));
|
||||
|
||||
template.execute(
|
||||
"CREATE CUSTOM INDEX IF NOT EXISTS fn_contains ON person (nickname) USING 'org.apache.cassandra.index.sasi.SASIIndex'\n"
|
||||
+ "WITH OPTIONS = { 'mode': 'CONTAINS' };");
|
||||
|
||||
// Give Cassandra some time to build the index
|
||||
Thread.sleep(500);
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ import com.datastax.driver.core.Session;
|
||||
|
||||
/**
|
||||
* Utility to retrieve the Cassandra release version.
|
||||
*
|
||||
*
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@UtilityClass
|
||||
@@ -34,7 +34,7 @@ public class CassandraVersion {
|
||||
|
||||
/**
|
||||
* Retrieve the Cassandra release version.
|
||||
*
|
||||
*
|
||||
* @param session must not be {@literal null}.
|
||||
* @return the release {@link Version}.
|
||||
*/
|
||||
@@ -44,6 +44,7 @@ public class CassandraVersion {
|
||||
|
||||
ResultSet resultSet = session.execute("SELECT release_version FROM system.local;");
|
||||
Row row = resultSet.one();
|
||||
|
||||
return Version.parse(row.getString(0));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user