DATACASS-360 - Polish.
This commit is contained in:
@@ -10,7 +10,7 @@
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements in the XML namespace for Spring Cassandra.
|
||||
Defines configuration elements in the XML namespace for Spring for Apache Cassandra.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -561,6 +561,37 @@ If the utilisation of opened connections drops below by this configured threshol
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="replicationType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Provides the ability to configure the keyspace's replication settings.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="data-center" type="datacenterType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Provides the ability to specify replication factors by data center.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="class" type="xsd:string" use="optional" default="SimpleStrategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the replication class; default is "SIMPLE_STRATEGY".
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-factor" type="xsd:string" use="optional" default="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The replication factor; default is 1.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="sessionType">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="startup-cql" type="xsd:string" minOccurs="0" maxOccurs="unbounded">
|
||||
@@ -660,37 +691,6 @@ Sets the SO_TCPNODELAY socket option.
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="replicationType">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Provides the ability to configure the keyspace's replication settings.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="data-center" type="datacenterType" minOccurs="0" maxOccurs="unbounded">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Provides the ability to specify replication factors by data center.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:element>
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="class" type="xsd:string" use="optional" default="SimpleStrategy">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The name of the replication class; default is "SIMPLE_STRATEGY".
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="replication-factor" type="xsd:string" use="optional" default="1">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The replication factor; default is 1.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="templateType">
|
||||
<xsd:attribute name="id" type="xsd:ID" use="optional">
|
||||
<xsd:annotation>
|
||||
|
||||
@@ -18,16 +18,12 @@ package org.springframework.data.cassandra.core;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.LinkedHashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.datastax.driver.core.KeyspaceMetadata;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.UserType;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
import org.springframework.cassandra.core.cql.generator.CreateTableCqlGenerator;
|
||||
@@ -52,8 +48,8 @@ import org.springframework.util.Assert;
|
||||
*/
|
||||
public class CassandraPersistentEntitySchemaCreator {
|
||||
|
||||
private final CassandraMappingContext mappingContext;
|
||||
private final CassandraAdminOperations cassandraAdminOperations;
|
||||
private final CassandraMappingContext mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraPersistentEntitySchemaCreator} for the given {@link CassandraMappingContext} and
|
||||
@@ -65,11 +61,11 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
public CassandraPersistentEntitySchemaCreator(CassandraMappingContext mappingContext,
|
||||
CassandraAdminOperations cassandraAdminOperations) {
|
||||
|
||||
Assert.notNull(mappingContext, "CassandraMappingContext must not be null");
|
||||
Assert.notNull(cassandraAdminOperations, "CassandraAdminOperations must not be null");
|
||||
Assert.notNull(mappingContext, "CassandraMappingContext must not be null");
|
||||
|
||||
this.mappingContext = mappingContext;
|
||||
this.cassandraAdminOperations = cassandraAdminOperations;
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -86,9 +82,22 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
dropTables(dropUnused);
|
||||
}
|
||||
|
||||
for (CreateTableSpecification specification : createTableSpecifications(ifNotExists)) {
|
||||
cassandraAdminOperations.getCqlOperations().execute(CreateTableCqlGenerator.toCql(specification));
|
||||
}
|
||||
createTableSpecifications(ifNotExists).forEach(specification ->
|
||||
cassandraAdminOperations.getCqlOperations().execute(CreateTableCqlGenerator.toCql(specification)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected List<CreateTableSpecification> createTableSpecifications(boolean ifNotExists) {
|
||||
return mappingContext.getTableEntities().stream()
|
||||
.map(entity -> mappingContext.getCreateTableSpecificationFor(entity).ifNotExists(ifNotExists))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void dropTables(boolean dropUnused) {
|
||||
cassandraAdminOperations.getKeyspaceMetadata().getTables().stream()
|
||||
.filter(table -> dropUnused || mappingContext.usesTable(table))
|
||||
.forEach(table -> cassandraAdminOperations.dropTable(CqlIdentifier.cqlId(table.getName())));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -106,67 +115,48 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
dropUserTypes(dropUnused);
|
||||
}
|
||||
|
||||
for (CreateUserTypeSpecification specification : createUserTypeSpecifications(ifNotExists)) {
|
||||
cassandraAdminOperations.getCqlOperations().execute(CreateUserTypeCqlGenerator.toCql(specification));
|
||||
}
|
||||
createUserTypeSpecifications(ifNotExists).forEach(specification ->
|
||||
cassandraAdminOperations.getCqlOperations().execute(CreateUserTypeCqlGenerator.toCql(specification)));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected List<CreateUserTypeSpecification> createUserTypeSpecifications(boolean ifNotExists) {
|
||||
|
||||
Collection<? extends CassandraPersistentEntity<?>> entities = new ArrayList<>(
|
||||
mappingContext.getUserDefinedTypeEntities());
|
||||
|
||||
Map<CqlIdentifier, CassandraPersistentEntity<?>> byName = new HashMap<>();
|
||||
|
||||
for (CassandraPersistentEntity<?> entity : entities) {
|
||||
byName.put(entity.getTableName(), entity);
|
||||
}
|
||||
Map<CqlIdentifier, CassandraPersistentEntity<?>> byTableName = entities.stream().collect(Collectors.toMap(
|
||||
CassandraPersistentEntity::getTableName, entity -> entity));
|
||||
|
||||
List<CreateUserTypeSpecification> specifications = new ArrayList<>();
|
||||
|
||||
// TODO is this Set really needed?
|
||||
Set<CqlIdentifier> created = new HashSet<>();
|
||||
|
||||
for (CassandraPersistentEntity<?> entity : entities) {
|
||||
|
||||
Set<CqlIdentifier> seen = new LinkedHashSet<>();
|
||||
|
||||
seen.add(entity.getTableName());
|
||||
visitUserTypes(entity, seen);
|
||||
|
||||
List<CqlIdentifier> ordered = new ArrayList<>(seen);
|
||||
Collections.reverse(ordered);
|
||||
|
||||
for (CqlIdentifier identifier : ordered) {
|
||||
if (created.add(identifier)) {
|
||||
specifications.add(mappingContext.getCreateUserTypeSpecificationFor(
|
||||
byName.get(identifier)).ifNotExists(ifNotExists));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return specifications;
|
||||
}
|
||||
|
||||
protected List<CreateTableSpecification> createTableSpecifications(boolean ifNotExists) {
|
||||
|
||||
Collection<? extends CassandraPersistentEntity<?>> entities = new ArrayList<>(
|
||||
mappingContext.getTableEntities());
|
||||
|
||||
List<CreateTableSpecification> specifications = new ArrayList<>();
|
||||
|
||||
for (CassandraPersistentEntity<?> entity : entities) {
|
||||
specifications.add(mappingContext.getCreateTableSpecificationFor(entity).ifNotExists(ifNotExists));
|
||||
specifications.addAll(ordered.stream().filter(created::add)
|
||||
.map(identifier -> mappingContext.getCreateUserTypeSpecificationFor(byTableName.get(identifier))
|
||||
.ifNotExists(ifNotExists)).collect(Collectors.toList()));
|
||||
}
|
||||
|
||||
return specifications;
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void visitUserTypes(CassandraPersistentEntity<?> entity, final Set<CqlIdentifier> seen) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty persistentProperty) {
|
||||
|
||||
CassandraPersistentEntity<?> persistentEntity = mappingContext.getPersistentEntity(persistentProperty);
|
||||
|
||||
if (persistentEntity != null && persistentEntity.isUserDefinedType()) {
|
||||
@@ -178,19 +168,13 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
});
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private void dropUserTypes(boolean dropUnused) {
|
||||
|
||||
Collection<CassandraPersistentEntity<?>> userDefinedTypeEntities = mappingContext.getUserDefinedTypeEntities();
|
||||
Set<CqlIdentifier> canRecreate = new HashSet<>();
|
||||
|
||||
for (CassandraPersistentEntity<?> userDefinedTypeEntity : userDefinedTypeEntities) {
|
||||
canRecreate.add(userDefinedTypeEntity.getTableName());
|
||||
}
|
||||
|
||||
KeyspaceMetadata keyspaceMetadata = cassandraAdminOperations.getKeyspaceMetadata();
|
||||
|
||||
for (UserType userType : keyspaceMetadata.getUserTypes()) {
|
||||
Set<CqlIdentifier> canRecreate = mappingContext.getUserDefinedTypeEntities().stream()
|
||||
.map(CassandraPersistentEntity::getTableName).collect(Collectors.toSet());
|
||||
|
||||
cassandraAdminOperations.getKeyspaceMetadata().getUserTypes().forEach(userType -> {
|
||||
CqlIdentifier identifier = CqlIdentifier.cqlId(userType.getTypeName());
|
||||
|
||||
if (canRecreate.contains(identifier)) {
|
||||
@@ -198,17 +182,6 @@ public class CassandraPersistentEntitySchemaCreator {
|
||||
} else if (dropUnused && !mappingContext.usesUserType(userType)) {
|
||||
cassandraAdminOperations.dropUserType(identifier);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void dropTables(boolean dropUnused) {
|
||||
|
||||
KeyspaceMetadata keyspaceMetadata = cassandraAdminOperations.getKeyspaceMetadata();
|
||||
|
||||
for (TableMetadata table : keyspaceMetadata.getTables()) {
|
||||
if (dropUnused || mappingContext.usesTable(table)) {
|
||||
cassandraAdminOperations.dropTable(CqlIdentifier.cqlId(table.getName()));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,10 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.UserType;
|
||||
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
|
||||
@@ -37,7 +41,6 @@ import org.springframework.cassandra.core.keyspace.CreateUserTypeSpecification;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.data.annotation.Persistent;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.PropertyHandler;
|
||||
import org.springframework.data.mapping.context.AbstractMappingContext;
|
||||
@@ -49,10 +52,6 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.UserType;
|
||||
|
||||
/**
|
||||
* Default implementation of a {@link MappingContext} for Cassandra using {@link CassandraPersistentEntity} and
|
||||
* {@link CassandraPersistentProperty} as primary abstractions.
|
||||
@@ -95,6 +94,84 @@ public class BasicCassandraMappingContext
|
||||
setSimpleTypeHolder(CassandraSimpleTypeHolder.HOLDER);
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
processMappingOverrides();
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
@SuppressWarnings("all")
|
||||
protected void processMappingOverrides() {
|
||||
|
||||
if (mapping != null) {
|
||||
mapping.getEntityMappings().stream().filter((entityMapping -> entityMapping != null))
|
||||
.forEach(entityMapping -> {
|
||||
String entityClassName = entityMapping.getEntityClassName();
|
||||
|
||||
try {
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
|
||||
|
||||
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
Assert.state(entity != null,
|
||||
String.format("Unknown persistent entity class name [%s]", entityClassName));
|
||||
|
||||
String entityTableName = entityMapping.getTableName();
|
||||
|
||||
if (StringUtils.hasText(entityTableName)) {
|
||||
entity.setTableName(cqlId(entityTableName, Boolean.valueOf(entityMapping.getForceQuote())));
|
||||
}
|
||||
|
||||
processMappingOverrides(entity, entityMapping);
|
||||
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new IllegalStateException(
|
||||
String.format("Unknown persistent entity name [%s]", entityClassName), e);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {
|
||||
entityMapping.getPropertyMappings().forEach(
|
||||
(key, propertyMapping) -> processMappingOverride(entity, propertyMapping));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
protected void processMappingOverride(CassandraPersistentEntity<?> entity, PropertyMapping mapping) {
|
||||
|
||||
CassandraPersistentProperty property = entity.getPersistentProperty(mapping.getPropertyName());
|
||||
|
||||
Assert.notNull(property, String.format("Entity class [%s] has no persistent property named [%s]",
|
||||
entity.getType().getName(), mapping.getPropertyName()));
|
||||
|
||||
boolean forceQuote = Boolean.valueOf(mapping.getForceQuote());
|
||||
|
||||
property.setForceQuote(forceQuote);
|
||||
|
||||
if (StringUtils.hasText(mapping.getColumnName())) {
|
||||
property.setColumnName(cqlId(mapping.getColumnName(), forceQuote));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.context = applicationContext;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link CustomConversions}.
|
||||
*
|
||||
@@ -108,6 +185,13 @@ public class BasicCassandraMappingContext
|
||||
this.customConversions = customConversions;
|
||||
}
|
||||
|
||||
public void setMapping(Mapping mapping) {
|
||||
|
||||
Assert.notNull(mapping, "Mapping must not be null");
|
||||
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the {@link UserTypeResolver}.
|
||||
*
|
||||
@@ -121,15 +205,25 @@ public class BasicCassandraMappingContext
|
||||
this.userTypeResolver = userTypeResolver;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param verifier The verifier to set.
|
||||
*/
|
||||
@Override
|
||||
public void initialize() {
|
||||
super.initialize();
|
||||
processMappingOverrides();
|
||||
public void setVerifier(CassandraPersistentEntityMetadataVerifier verifier) {
|
||||
this.verifier = verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the verifier.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public CassandraPersistentEntityMetadataVerifier getVerifier() {
|
||||
return verifier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CassandraPersistentEntity<?>> getTableEntities() {
|
||||
return Collections.unmodifiableCollection(tableEntities);
|
||||
public Collection<CassandraPersistentEntity<?>> getNonPrimaryKeyEntities() {
|
||||
return getTableEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -138,8 +232,8 @@ public class BasicCassandraMappingContext
|
||||
}
|
||||
|
||||
@Override
|
||||
public Collection<CassandraPersistentEntity<?>> getNonPrimaryKeyEntities() {
|
||||
return getTableEntities();
|
||||
public Collection<CassandraPersistentEntity<?>> getTableEntities() {
|
||||
return Collections.unmodifiableCollection(tableEntities);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -161,24 +255,11 @@ public class BasicCassandraMappingContext
|
||||
return getTableEntities();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
return createPersistentProperty(field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder);
|
||||
}
|
||||
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
return new BasicCassandraPersistentProperty(field, descriptor, owner, simpleTypeHolder, userTypeResolver);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected <T> CassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
|
||||
|
||||
UserDefinedType userDefinedType = AnnotatedElementUtils.findMergedAnnotation(typeInformation.getType(),
|
||||
UserDefinedType.class);
|
||||
UserDefinedType userDefinedType = AnnotatedElementUtils.findMergedAnnotation(
|
||||
typeInformation.getType(), UserDefinedType.class);
|
||||
|
||||
CassandraPersistentEntity<T> entity;
|
||||
|
||||
@@ -219,12 +300,17 @@ public class BasicCassandraMappingContext
|
||||
return entity;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.context.ApplicationContextAware#setApplicationContext(org.springframework.context.ApplicationContext)
|
||||
*/
|
||||
@Override
|
||||
public void setApplicationContext(ApplicationContext applicationContext) throws BeansException {
|
||||
this.context = applicationContext;
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
CassandraPersistentEntity<?> owner, SimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
return createPersistentProperty(field, descriptor, owner, (CassandraSimpleTypeHolder) simpleTypeHolder);
|
||||
}
|
||||
|
||||
public CassandraPersistentProperty createPersistentProperty(Field field, PropertyDescriptor descriptor,
|
||||
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
|
||||
|
||||
return new BasicCassandraPersistentProperty(field, descriptor, owner, simpleTypeHolder, userTypeResolver);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -250,9 +336,8 @@ public class BasicCassandraMappingContext
|
||||
|
||||
final AtomicBoolean foundReference = new AtomicBoolean();
|
||||
|
||||
for (CassandraPersistentEntity<?> entity : getPersistentEntities()) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
getPersistentEntities().forEach(entity -> entity.doWithProperties(
|
||||
new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty persistentProperty) {
|
||||
@@ -264,12 +349,11 @@ public class BasicCassandraMappingContext
|
||||
}
|
||||
|
||||
if (StringUtils.hasText(cassandraType.userTypeName())
|
||||
&& CqlIdentifier.cqlId(cassandraType.userTypeName()).equals(identifier)) {
|
||||
&& CqlIdentifier.cqlId(cassandraType.userTypeName()).equals(identifier)) {
|
||||
foundReference.set(true);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}));
|
||||
|
||||
return foundReference.get();
|
||||
}
|
||||
@@ -290,55 +374,54 @@ public class BasicCassandraMappingContext
|
||||
|
||||
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
|
||||
|
||||
final CreateTableSpecification spec = createTable().name(entity.getTableName());
|
||||
final CreateTableSpecification specification = createTable().name(entity.getTableName());
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty property) {
|
||||
|
||||
if (property.isCompositePrimaryKey()) {
|
||||
|
||||
CassandraPersistentEntity<?> primaryKeyEntity = getPersistentEntity(property.getRawType());
|
||||
|
||||
primaryKeyEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty primaryKeyProperty) {
|
||||
|
||||
if (primaryKeyProperty.isPartitionKeyColumn()) {
|
||||
spec.partitionKeyColumn(primaryKeyProperty.getColumnName(), getDataType(primaryKeyProperty));
|
||||
specification.partitionKeyColumn(primaryKeyProperty.getColumnName(),
|
||||
getDataType(primaryKeyProperty));
|
||||
}
|
||||
else { // it's a cluster column
|
||||
spec.clusteredKeyColumn(primaryKeyProperty.getColumnName(),
|
||||
getDataType(primaryKeyProperty),
|
||||
primaryKeyProperty.getPrimaryKeyOrdering());
|
||||
specification.clusteredKeyColumn(primaryKeyProperty.getColumnName(),
|
||||
getDataType(primaryKeyProperty), primaryKeyProperty.getPrimaryKeyOrdering());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
if (property.isIdProperty() || property.isPartitionKeyColumn()) {
|
||||
spec.partitionKeyColumn(property.getColumnName(), getDataType(property));
|
||||
specification.partitionKeyColumn(property.getColumnName(), getDataType(property));
|
||||
}
|
||||
else if (property.isClusterKeyColumn()) {
|
||||
spec.clusteredKeyColumn(property.getColumnName(), getDataType(property), property.getPrimaryKeyOrdering());
|
||||
specification.clusteredKeyColumn(property.getColumnName(), getDataType(property),
|
||||
property.getPrimaryKeyOrdering());
|
||||
}
|
||||
else {
|
||||
spec.column(property.getColumnName(), getDataType(property));
|
||||
specification.column(property.getColumnName(), getDataType(property));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (spec.getPartitionKeyColumns().isEmpty()) {
|
||||
if (specification.getPartitionKeyColumns().isEmpty()) {
|
||||
throw new MappingException(String.format("No partition key columns found in entity [%s]", entity.getType()));
|
||||
}
|
||||
|
||||
return spec;
|
||||
return specification;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.mapping.CassandraMappingContext#getCreateUserTypeSpecificationFor(org.springframework.data.cassandra.mapping.CassandraPersistentEntity)
|
||||
*/
|
||||
@Override
|
||||
@@ -346,21 +429,21 @@ public class BasicCassandraMappingContext
|
||||
|
||||
Assert.notNull(entity, "CassandraPersistentEntity must not be null");
|
||||
|
||||
final CreateUserTypeSpecification spec = CreateUserTypeSpecification.createType(entity.getTableName());
|
||||
final CreateUserTypeSpecification specification = CreateUserTypeSpecification.createType(entity.getTableName());
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty property) {
|
||||
spec.field(property.getColumnName(), getDataType(property));
|
||||
specification.field(property.getColumnName(), getDataType(property));
|
||||
}
|
||||
});
|
||||
|
||||
if (spec.getFields().isEmpty()) {
|
||||
if (specification.getFields().isEmpty()) {
|
||||
throw new MappingException(String.format("No fields in user type [%s]", entity.getType()));
|
||||
}
|
||||
|
||||
return spec;
|
||||
return specification;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -406,18 +489,16 @@ public class BasicCassandraMappingContext
|
||||
}
|
||||
|
||||
if (customConversions.hasCustomWriteTarget(property.getActualType())) {
|
||||
|
||||
Class<?> targetType = customConversions.getCustomWriteTarget(property.getActualType());
|
||||
|
||||
if (property.isCollectionLike()) {
|
||||
if (List.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.list(getDataTypeFor(targetType));
|
||||
}
|
||||
|
||||
if (Set.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.set(getDataTypeFor(targetType));
|
||||
}
|
||||
|
||||
if (List.class.isAssignableFrom(property.getType())) {
|
||||
return DataType.list(getDataTypeFor(targetType));
|
||||
}
|
||||
}
|
||||
|
||||
return getDataTypeFor(targetType);
|
||||
@@ -435,82 +516,6 @@ public class BasicCassandraMappingContext
|
||||
? getDataTypeFor(customConversions.getCustomWriteTarget(type)) : getDataTypeFor(type));
|
||||
}
|
||||
|
||||
public void setMapping(Mapping mapping) {
|
||||
Assert.notNull(mapping, "Mapping must not be null");
|
||||
|
||||
this.mapping = mapping;
|
||||
}
|
||||
|
||||
@SuppressWarnings("all")
|
||||
protected void processMappingOverrides() {
|
||||
|
||||
if (mapping == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (EntityMapping entityMapping : mapping.getEntityMappings()) {
|
||||
|
||||
if (entityMapping == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
String entityClassName = entityMapping.getEntityClassName();
|
||||
|
||||
try {
|
||||
Class<?> entityClass = ClassUtils.forName(entityClassName, beanClassLoader);
|
||||
|
||||
CassandraPersistentEntity<?> entity = getPersistentEntity(entityClass);
|
||||
|
||||
Assert.state(entity != null,
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMappingOverrides(CassandraPersistentEntity<?> entity, EntityMapping entityMapping) {
|
||||
for (PropertyMapping mapping : entityMapping.getPropertyMappings().values()) {
|
||||
processMappingOverride(entity, mapping);
|
||||
}
|
||||
}
|
||||
|
||||
protected void processMappingOverride(CassandraPersistentEntity<?> entity, PropertyMapping mapping) {
|
||||
|
||||
CassandraPersistentProperty property = entity.getPersistentProperty(mapping.getPropertyName());
|
||||
|
||||
Assert.notNull(property, String.format("Entity class [%s] has no persistent property named [%s]",
|
||||
entity.getType().getName(), mapping.getPropertyName()));
|
||||
|
||||
boolean forceQuote = false;
|
||||
|
||||
String value = mapping.getForceQuote();
|
||||
|
||||
if (StringUtils.hasText(value)) {
|
||||
property.setForceQuote(forceQuote = Boolean.valueOf(value));
|
||||
}
|
||||
|
||||
value = mapping.getColumnName();
|
||||
|
||||
if (StringUtils.hasText(value)) {
|
||||
property.setColumnName(cqlId(value, forceQuote));
|
||||
}
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader beanClassLoader) {
|
||||
this.beanClassLoader = beanClassLoader;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CassandraPersistentEntity<?> getExistingPersistentEntity(Class<?> type) {
|
||||
|
||||
@@ -525,20 +530,4 @@ public class BasicCassandraMappingContext
|
||||
public boolean contains(Class<?> type) {
|
||||
return entitiesByType.containsKey(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the verifier.
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public CassandraPersistentEntityMetadataVerifier getVerifier() {
|
||||
return verifier;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param verifier The verifier to set.
|
||||
*/
|
||||
@Override
|
||||
public void setVerifier(CassandraPersistentEntityMetadataVerifier verifier) {
|
||||
this.verifier = verifier;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -17,18 +17,18 @@ package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.UserType;
|
||||
|
||||
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
|
||||
import org.springframework.cassandra.core.keyspace.CreateUserTypeSpecification;
|
||||
import org.springframework.data.cassandra.convert.CustomConversions;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.TableMetadata;
|
||||
import com.datastax.driver.core.UserType;
|
||||
|
||||
/**
|
||||
* A {@link MappingContext} for Cassandra.
|
||||
*
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
* @author Mark Paluch
|
||||
*/
|
||||
@@ -37,27 +37,29 @@ public interface CassandraMappingContext
|
||||
|
||||
/**
|
||||
* Returns only those entities that don't represent primary key types.
|
||||
*
|
||||
*
|
||||
* @see #getPersistentEntities(boolean)
|
||||
*/
|
||||
@Override
|
||||
Collection<CassandraPersistentEntity<?>> getPersistentEntities();
|
||||
|
||||
/**
|
||||
* Returns only {@link Table} entities.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
Collection<CassandraPersistentEntity<?>> getTableEntities();
|
||||
|
||||
/**
|
||||
* Returns all persistent entities or only non-primary-key entities.
|
||||
*
|
||||
*
|
||||
* @param includePrimaryKeyTypesAndUdts If {@literal true}, returns all entities, including entities that represent primary
|
||||
* key types and user-defined types. If {@literal false}, returns only entities that don't represent primary key types and no user-defined types.
|
||||
*/
|
||||
Collection<CassandraPersistentEntity<?>> getPersistentEntities(boolean includePrimaryKeyTypesAndUdts);
|
||||
|
||||
/**
|
||||
* Returns only those entities not representing primary key types.
|
||||
*
|
||||
* @see #getPersistentEntities(boolean)
|
||||
* @deprecated as of 1.5, use {@link #getTableEntities()}.
|
||||
*/
|
||||
@Deprecated
|
||||
Collection<CassandraPersistentEntity<?>> getNonPrimaryKeyEntities();
|
||||
|
||||
/**
|
||||
* Returns only those entities representing primary key types.
|
||||
* @deprecated as of 1.5
|
||||
@@ -66,13 +68,11 @@ public interface CassandraMappingContext
|
||||
Collection<CassandraPersistentEntity<?>> getPrimaryKeyEntities();
|
||||
|
||||
/**
|
||||
* Returns only those entities not representing primary key types.
|
||||
*
|
||||
* @see #getPersistentEntities(boolean)
|
||||
* @deprecated as of 1.5, use {@link #getTableEntities()}.
|
||||
* Returns only {@link Table} entities.
|
||||
*
|
||||
* @since 1.5
|
||||
*/
|
||||
@Deprecated
|
||||
Collection<CassandraPersistentEntity<?>> getNonPrimaryKeyEntities();
|
||||
Collection<CassandraPersistentEntity<?>> getTableEntities();
|
||||
|
||||
/**
|
||||
* Returns only those entities representing a user defined type.
|
||||
@@ -84,7 +84,7 @@ public interface CassandraMappingContext
|
||||
|
||||
/**
|
||||
* Returns a {@link CreateTableSpecification} for the given entity, including all mapping information.
|
||||
*
|
||||
*
|
||||
* @param entity must not be {@literal null}.
|
||||
*/
|
||||
CreateTableSpecification getCreateTableSpecificationFor(CassandraPersistentEntity<?> entity);
|
||||
@@ -98,7 +98,7 @@ public interface CassandraMappingContext
|
||||
|
||||
/**
|
||||
* Returns whether this mapping context has any entities mapped to the given table.
|
||||
*
|
||||
*
|
||||
* @param table must not be {@literal null}.
|
||||
* @return @return {@literal true} is this {@literal TableMetadata} is used by a mapping.
|
||||
*/
|
||||
@@ -116,7 +116,7 @@ public interface CassandraMappingContext
|
||||
/**
|
||||
* Returns the existing {@link CassandraPersistentEntity} for the given {@link Class}. If it is not yet known to this
|
||||
* {@link CassandraMappingContext}, an {@link IllegalArgumentException} is thrown.
|
||||
*
|
||||
*
|
||||
* @param type The class of the existing persistent entity.
|
||||
* @return The existing persistent entity.
|
||||
*/
|
||||
@@ -156,4 +156,5 @@ public interface CassandraMappingContext
|
||||
* @since 1.5
|
||||
*/
|
||||
DataType getDataType(Class<?> type);
|
||||
|
||||
}
|
||||
|
||||
@@ -64,8 +64,6 @@ public class CompositeCassandraPersistentEntityMetadataVerifier implements Cassa
|
||||
*/
|
||||
@Override
|
||||
public void verify(CassandraPersistentEntity<?> entity) throws MappingException {
|
||||
for (CassandraPersistentEntityMetadataVerifier verifier : verifiers) {
|
||||
verifier.verify(entity);
|
||||
}
|
||||
verifiers.forEach(verifier -> verifier.verify(entity));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -20,40 +20,41 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Mapping information for an individual entity class.
|
||||
*
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
* @author John Blum
|
||||
*/
|
||||
public class EntityMapping {
|
||||
|
||||
/**
|
||||
* The name of the entity's class.
|
||||
* The {@link PropertyMapping}s for each persistent property, keyed on property name.
|
||||
*/
|
||||
protected String entityClassName;
|
||||
private Map<String, PropertyMapping> propertyMappings = Collections.emptyMap();
|
||||
|
||||
/**
|
||||
* The name of the table to which the entity is mapped.
|
||||
* The name of the entity's class.
|
||||
*/
|
||||
protected String tableName = "";
|
||||
private String entityClassName;
|
||||
|
||||
/**
|
||||
* Whether to force the table name to be quoted.
|
||||
*/
|
||||
protected String forceQuote = "false";
|
||||
private String forceQuote = "false";
|
||||
|
||||
/**
|
||||
* The {@link PropertyMapping}s for each persistent property, keyed on property name.
|
||||
* The name of the table to which the entity is mapped.
|
||||
*/
|
||||
protected Map<String, PropertyMapping> propertyMappings = new HashMap<String, PropertyMapping>();
|
||||
private String tableName = "";
|
||||
|
||||
public EntityMapping(String entityClassName, String tableName) {
|
||||
this(entityClassName, tableName, Boolean.FALSE.toString());
|
||||
}
|
||||
|
||||
public EntityMapping(String entityClassName, String tableName, String forceQuote) {
|
||||
|
||||
setEntityClassName(entityClassName);
|
||||
setTableName(tableName);
|
||||
setForceQuote(forceQuote);
|
||||
@@ -64,60 +65,90 @@ public class EntityMapping {
|
||||
}
|
||||
|
||||
public void setEntityClassName(String entityClassName) {
|
||||
|
||||
Assert.hasText(entityClassName);
|
||||
this.entityClassName = entityClassName;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
|
||||
Assert.notNull(tableName);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public String getForceQuote() {
|
||||
return forceQuote;
|
||||
}
|
||||
|
||||
public void setForceQuote(String forceQuote) {
|
||||
|
||||
Assert.notNull(forceQuote);
|
||||
this.forceQuote = forceQuote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
if (this == that) {
|
||||
return true;
|
||||
}
|
||||
if (!(that instanceof EntityMapping)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityMapping other = (EntityMapping) that;
|
||||
|
||||
return this.entityClassName.equals(other.entityClassName) && this.forceQuote.equals(other.forceQuote)
|
||||
&& this.tableName.equals(other.tableName);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return entityClassName.hashCode() ^ forceQuote.hashCode() ^ tableName.hashCode();
|
||||
}
|
||||
|
||||
public void setPropertyMappings(Map<String, PropertyMapping> propertyMappings) {
|
||||
propertyMappings = propertyMappings == null ? new HashMap<String, PropertyMapping>() : propertyMappings;
|
||||
this.propertyMappings = new HashMap<String, PropertyMapping>(propertyMappings);
|
||||
}
|
||||
|
||||
public Map<String, PropertyMapping> getPropertyMappings() {
|
||||
return Collections.unmodifiableMap(propertyMappings);
|
||||
}
|
||||
|
||||
public void setPropertyMappings(Map<String, PropertyMapping> propertyMappings) {
|
||||
this.propertyMappings = (propertyMappings != null ? new HashMap<String, PropertyMapping>(propertyMappings)
|
||||
: Collections.<String, PropertyMapping>emptyMap());
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
Assert.notNull(tableName);
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (!(obj instanceof EntityMapping)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EntityMapping that = (EntityMapping) obj;
|
||||
|
||||
return ObjectUtils.nullSafeEquals(this.getEntityClassName(), that.getEntityClassName())
|
||||
&& ObjectUtils.nullSafeEquals(this.getForceQuote(), that.getForceQuote())
|
||||
&& ObjectUtils.nullSafeEquals(this.getTableName(), that.getTableName());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashValue = 17;
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getEntityClassName());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getForceQuote());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getTableName());
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
"{ @type = %1$s, entityClassName = %2$s, tableName = %3$s, forceQuote = %4$s, propertyMappings = %5$s }",
|
||||
getClass().getName(), getEntityClassName(), getTableName(), getForceQuote(),
|
||||
toString(getPropertyMappings()));
|
||||
}
|
||||
|
||||
/* (non-Javadoc) */
|
||||
private String toString(Map<?, ?> map) {
|
||||
StringBuilder builder = new StringBuilder("[");
|
||||
int count = 0;
|
||||
|
||||
for (Map.Entry<?, ?> entry : map.entrySet()) {
|
||||
builder.append(++count > 1 ? ", " : "");
|
||||
builder.append(String.format("%1$s = %2$s", entry.getKey(), entry.getValue()));
|
||||
}
|
||||
|
||||
return builder.toString();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
@@ -15,21 +15,20 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.mapping;
|
||||
|
||||
import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId;
|
||||
import static org.springframework.cassandra.core.cql.CqlIdentifier.quotedCqlId;
|
||||
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
/**
|
||||
* Mapping between a persistent entity's property and its column.
|
||||
*
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
* @author John Blum
|
||||
*/
|
||||
public class PropertyMapping {
|
||||
|
||||
protected String propertyName;
|
||||
protected String columnName;
|
||||
protected String forceQuote;
|
||||
private String columnName;
|
||||
private String forceQuote;
|
||||
private String propertyName;
|
||||
|
||||
public PropertyMapping(String propertyName) {
|
||||
setPropertyName(propertyName);
|
||||
@@ -40,21 +39,11 @@ public class PropertyMapping {
|
||||
}
|
||||
|
||||
public PropertyMapping(String propertyName, String columnName, String forceQuote) {
|
||||
|
||||
setPropertyName(propertyName);
|
||||
setColumnName(columnName);
|
||||
setForceQuote(forceQuote);
|
||||
}
|
||||
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
public void setPropertyName(String propertyName) {
|
||||
Assert.notNull(propertyName);
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
@@ -72,54 +61,53 @@ public class PropertyMapping {
|
||||
this.forceQuote = forceQuote;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object that) {
|
||||
public String getPropertyName() {
|
||||
return propertyName;
|
||||
}
|
||||
|
||||
if (this == that) {
|
||||
public void setPropertyName(String propertyName) {
|
||||
Assert.notNull(propertyName);
|
||||
this.propertyName = propertyName;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj) {
|
||||
return true;
|
||||
}
|
||||
if (that == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(that instanceof PropertyMapping)) {
|
||||
|
||||
if (!(obj instanceof PropertyMapping)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
PropertyMapping other = (PropertyMapping) that;
|
||||
PropertyMapping that = (PropertyMapping) obj;
|
||||
|
||||
if (this.propertyName == null) {
|
||||
if (other.propertyName != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!this.propertyName.equals(other.propertyName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.columnName == null) {
|
||||
if (other.columnName != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (!this.columnName.equals(other.columnName)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.forceQuote == null) {
|
||||
if (other.forceQuote != null) {
|
||||
return false;
|
||||
}
|
||||
} else if (this.forceQuote.equals(other.forceQuote)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
return ObjectUtils.nullSafeEquals(this.getPropertyName(), that.getPropertyName())
|
||||
&& ObjectUtils.nullSafeEquals(this.getColumnName(), that.getColumnName())
|
||||
&& ObjectUtils.nullSafeEquals(this.getForceQuote(), that.getForceQuote());
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hashCode = 37;
|
||||
hashCode ^= propertyName == null ? 0 : propertyName.hashCode();
|
||||
hashCode ^= columnName == null ? 0 : columnName.hashCode();
|
||||
hashCode ^= forceQuote == null ? 0 : forceQuote.hashCode();
|
||||
return hashCode;
|
||||
int hashValue = 17;
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getPropertyName());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getColumnName());
|
||||
hashValue = 37 * hashValue + ObjectUtils.nullSafeHashCode(this.getForceQuote());
|
||||
return hashValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("{ @type = %1$s, propertyName = %2$s, columnName = %3$s, forceQuote = %4$s }",
|
||||
getClass().getName(), getPropertyName(), getColumnName(), getForceQuote());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -26,6 +24,9 @@ import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
@@ -47,8 +48,7 @@ import org.springframework.data.repository.query.ReturnedType;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
|
||||
/**
|
||||
* Base class for {@link RepositoryQuery} implementations for Cassandra.
|
||||
@@ -60,8 +60,8 @@ public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
|
||||
protected static Logger log = LoggerFactory.getLogger(AbstractCassandraQuery.class);
|
||||
|
||||
private final CassandraQueryMethod queryMethod;
|
||||
private final CassandraOperations template;
|
||||
private final CassandraQueryMethod queryMethod;
|
||||
private final EntityInstantiators instantiators;
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,10 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import com.datastax.driver.core.querybuilder.Clause;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
@@ -33,17 +37,12 @@ import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.domain.Sort.Order;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
import org.springframework.data.repository.core.EntityMetadata;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
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 com.datastax.driver.core.querybuilder.Clause;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* Custom query creator to create Cassandra criteria.
|
||||
*
|
||||
@@ -53,13 +52,13 @@ import com.datastax.driver.core.querybuilder.Select;
|
||||
*/
|
||||
class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
|
||||
private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("\\p{Punct}");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CassandraQueryCreator.class);
|
||||
private static final Pattern PUNCTUATION_PATTERN = Pattern.compile("\\p{Punct}");
|
||||
|
||||
private final CassandraMappingContext mappingContext;
|
||||
private final CassandraPersistentEntity<?> entity;
|
||||
private final WhereBuilder whereBuilder = new WhereBuilder();
|
||||
private final CqlIdentifier tableName;
|
||||
private final WhereBuilder whereBuilder = new WhereBuilder();
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor}
|
||||
@@ -89,7 +88,9 @@ class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
@Override
|
||||
protected Clause create(Part part, Iterator<Object> iterator) {
|
||||
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path = mappingContext.getPersistentPropertyPath(part.getProperty());
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path =
|
||||
mappingContext.getPersistentPropertyPath(part.getProperty());
|
||||
|
||||
CassandraPersistentProperty property = path.getLeafProperty();
|
||||
|
||||
return from(part, property, (PotentiallyConvertingIterator) iterator);
|
||||
|
||||
@@ -17,6 +17,8 @@ package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
import org.springframework.core.annotation.AnnotatedElementUtils;
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
@@ -32,8 +34,6 @@ import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
/**
|
||||
* Cassandra specific implementation of {@link QueryMethod}.
|
||||
*
|
||||
@@ -100,7 +100,6 @@ public class CassandraQueryMethod extends QueryMethod {
|
||||
mappingContext.getPersistentEntity(domainClass));
|
||||
|
||||
} else {
|
||||
|
||||
CassandraPersistentEntity<?> returnedEntity = mappingContext.getPersistentEntity(returnedObjectType);
|
||||
CassandraPersistentEntity<?> managedEntity = mappingContext.getPersistentEntity(domainClass);
|
||||
|
||||
|
||||
@@ -43,7 +43,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
|
||||
/**
|
||||
* Creates a new {@link Converter} to instantiate DTOs.
|
||||
*
|
||||
*
|
||||
* @param dtoType must not be {@literal null}.
|
||||
* @param context must not be {@literal null}.
|
||||
* @param instantiators must not be {@literal null}.
|
||||
@@ -61,7 +61,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
this.instantiator = instantiator.getInstantiatorFor(context.getPersistentEntity(dtoType));
|
||||
}
|
||||
|
||||
/*
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.core.convert.converter.Converter#convert(java.lang.Object)
|
||||
*/
|
||||
@@ -75,8 +75,6 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
final PersistentEntity<?, ?> sourceEntity = context.getPersistentEntity(source.getClass());
|
||||
final PersistentPropertyAccessor sourceAccessor = sourceEntity.getPropertyAccessor(source);
|
||||
final PersistentEntity<?, ?> targetEntity = context.getPersistentEntity(targetType);
|
||||
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor = targetEntity
|
||||
.getPersistenceConstructor();
|
||||
|
||||
@SuppressWarnings({ "rawtypes", "unchecked" })
|
||||
Object dto = instantiator.createInstance(targetEntity, new ParameterValueProvider() {
|
||||
@@ -87,7 +85,9 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
}
|
||||
});
|
||||
|
||||
final PersistentPropertyAccessor dtoAccessor = targetEntity.getPropertyAccessor(dto);
|
||||
final PersistentPropertyAccessor targetAccessor = targetEntity.getPropertyAccessor(dto);
|
||||
final PreferredConstructor<?, ? extends PersistentProperty<?>> constructor =
|
||||
targetEntity.getPersistenceConstructor();
|
||||
|
||||
targetEntity.doWithProperties(new SimplePropertyHandler() {
|
||||
|
||||
@@ -98,7 +98,7 @@ class DtoInstantiatingConverter implements Converter<Object, Object> {
|
||||
return;
|
||||
}
|
||||
|
||||
dtoAccessor.setProperty(property,
|
||||
targetAccessor.setProperty(property,
|
||||
sourceAccessor.getProperty(sourceEntity.getPersistentProperty(property.getName())));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
Defines the configuration elements in the XML namespace for Spring Data Cassandra.
|
||||
Defines configuration elements in the XML namespace for Spring Data for Apache Cassandra.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
|
||||
@@ -736,38 +736,7 @@ The reference to a Cassandra session; default is "cassandra-session".
|
||||
</xsd:attribute>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:attributeGroup name="cassandra-repository-attributes">
|
||||
<xsd:attribute name="cassandra-template-ref" type="cassandraTemplateRef">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a cassandraTemplate. Will default to 'cassandraTemplate'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:element name="repositories">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="repository:repositories">
|
||||
<xsd:attributeGroup ref="cassandra-repository-attributes" />
|
||||
<xsd:attributeGroup ref="repository:repository-attributes" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:simpleType name="cassandraTemplateRef" final="union">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to
|
||||
type="org.springframework.data.cassandra.core.CassandraTemplate" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
<!-- Spring Data Repository and Mapping (Persistence) Schema Elements -->
|
||||
|
||||
<xsd:element name="converter">
|
||||
<xsd:annotation>
|
||||
@@ -827,6 +796,27 @@ The reference to a UserTypeResolver. UserTypeResolver is required when working w
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="repositories">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="repository:repositories">
|
||||
<xsd:attributeGroup ref="cassandra-repository-attributes" />
|
||||
<xsd:attributeGroup ref="repository:repository-attributes" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:attributeGroup name="cassandra-repository-attributes">
|
||||
<xsd:attribute name="cassandra-template-ref" type="cassandraTemplateRef">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation><![CDATA[
|
||||
The reference to a CassandraTemplate. Will default to 'cassandraTemplate'.
|
||||
]]></xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
</xsd:attributeGroup>
|
||||
|
||||
<xsd:simpleType name="cassandraConverterRef" final="union">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
@@ -838,6 +828,18 @@ The reference to a UserTypeResolver. UserTypeResolver is required when working w
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="cassandraTemplateRef" final="union">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
<tool:annotation kind="ref">
|
||||
<tool:assignable-to
|
||||
type="org.springframework.data.cassandra.core.CassandraTemplate" />
|
||||
</tool:annotation>
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
<xsd:union memberTypes="xsd:string"/>
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:simpleType name="mappingContextRef">
|
||||
<xsd:annotation>
|
||||
<xsd:appinfo>
|
||||
|
||||
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.test.integration.repository.querymethods.derived;
|
||||
|
||||
import static org.assertj.core.api.Assertions.*;
|
||||
import static org.junit.Assume.*;
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
import static org.junit.Assume.assumeTrue;
|
||||
|
||||
import java.time.LocalDate;
|
||||
import java.util.Arrays;
|
||||
@@ -24,6 +24,7 @@ import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.datastax.driver.core.Session;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
@@ -200,7 +201,7 @@ public class QueryDerivationIntegrationTests extends AbstractSpringDataEmbeddedC
|
||||
@Test
|
||||
public void executesCollectionQueryWithDtoDynamicallyProjected() throws Exception {
|
||||
|
||||
template.execute(
|
||||
template.getCqlOperations().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
|
||||
|
||||
Reference in New Issue
Block a user