Merge branch 'DATACASS-33'

This commit is contained in:
Matthew Adams
2014-02-06 17:37:54 -06:00
69 changed files with 1932 additions and 1862 deletions

View File

@@ -18,16 +18,17 @@ package org.springframework.cassandra.core;
import com.datastax.driver.core.ResultSetFuture;
/**
* @author David Webb
* Interface used to give an implementation access to a {@link ResultSetFuture} after the query has completed.
*
* @author David Webb
*/
public interface AsynchronousQueryListener {
/**
* Called upon Query Completion.
*
* @param rsf The given ResultSetFuture's get methods should return immediately.
* @param rsf The {@link ResultSetFuture}. Since this isn't called until the asynchronous query completes, it can be
* immediately interrogated.
*/
public void onQueryComplete(ResultSetFuture rsf);
}

View File

@@ -21,8 +21,17 @@ import java.util.Map;
import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import org.springframework.cassandra.core.keyspace.AlterKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import org.springframework.cassandra.core.keyspace.CreateIndexSpecification;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.DropIndexSpecification;
import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
import org.springframework.dao.DataAccessException;
import com.datastax.driver.core.Query;
import com.datastax.driver.core.ResultSet;
import com.datastax.driver.core.ResultSetFuture;
import com.datastax.driver.core.Session;
@@ -52,12 +61,26 @@ public interface CqlOperations {
void execute(String cql) throws DataAccessException;
/**
* Executes the supplied CQL Query Asynchronously and returns nothing.
* Executes the supplied Query and returns nothing.
*
* @param cql The CQL Statement to execute
* @param query The {@link Query} to execute
*/
void execute(Query query) throws DataAccessException;
/**
* Executes the supplied Query Asynchronously and returns nothing.
*
* @param cql The {@link Query} to execute
*/
void executeAsynchronously(String cql) throws DataAccessException;
/**
* Executes the supplied CQL Query Asynchronously and returns nothing.
*
* @param query The {@link Query} to execute
*/
void executeAsynchronously(Query query) throws DataAccessException;
/**
* Executes the provided CQL Query, and extracts the results with the ResultSetExtractor. This uses default Query
* Options when extracting the ResultSet.
@@ -100,10 +123,10 @@ public interface CqlOperations {
ResultSetFuture queryAsynchronously(String cql, QueryOptions options);
/**
* Executes the provided CQL Query with the provided Runnable implementations.
* Executes the provided CQL Query with the provided {@link Runnable} implementation.
*
* @param cql The Query
* @param listener Runnable Listener for handling the query in a separate thread
* @param listener {@link Runnable} listener for handling the query in a separate thread
*/
void queryAsynchronously(String cql, Runnable listener);
@@ -113,7 +136,8 @@ public interface CqlOperations {
* query is completed for optimal flexibility.
*
* @param cql The Query
* @param listener Runnable Listener for handling the query in a separate thread
* @param listener {@link AsynchronousQueryListener} Listener for handling the query's {@link ResultSetFuture} in a
* separate thread
*/
void queryAsynchronously(String cql, AsynchronousQueryListener listener);
@@ -181,6 +205,23 @@ public interface CqlOperations {
*/
void queryAsynchronously(String cql, AsynchronousQueryListener listener, QueryOptions options, Executor executor);
/**
* Executes the provided CQL query and returns the {@link ResultSet}.
*
* @param cql The query
* @return The {@link ResultSet}
*/
ResultSet query(String cql);
/**
* Executes the provided CQL query with the given {@link QueryOptions} and returns the {@link ResultSet}.
*
* @param cql The query
* @param options The {@link QueryOptions}; may be null.
* @return The {@link ResultSet}
*/
ResultSet query(String cql, QueryOptions options);
/**
* Executes the provided CQL Query, and extracts the results with the ResultSetExtractor.
*
@@ -754,4 +795,67 @@ public interface CqlOperations {
*/
void truncate(String tableName);
/**
* Counts all rows for given table
*
* @param tableName
* @return
*/
long count(String tableName);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(DropTableSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(CreateTableSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(AlterTableSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(DropKeyspaceSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(CreateKeyspaceSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(AlterKeyspaceSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(DropIndexSpecification specification);
/**
* Convenience method to convert the given specification to CQL and execute it.
*
* @param specification The specification to execute; must not be null.
*/
ResultSet execute(CreateIndexSpecification specification);
}

View File

@@ -27,8 +27,25 @@ import java.util.concurrent.Executor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.springframework.cassandra.core.cql.generator.AlterKeyspaceCqlGenerator;
import org.springframework.cassandra.core.cql.generator.AlterTableCqlGenerator;
import org.springframework.cassandra.core.cql.generator.CreateIndexCqlGenerator;
import org.springframework.cassandra.core.cql.generator.CreateKeyspaceCqlGenerator;
import org.springframework.cassandra.core.cql.generator.CreateTableCqlGenerator;
import org.springframework.cassandra.core.cql.generator.DropIndexCqlGenerator;
import org.springframework.cassandra.core.cql.generator.DropKeyspaceCqlGenerator;
import org.springframework.cassandra.core.cql.generator.DropTableCqlGenerator;
import org.springframework.cassandra.core.keyspace.AlterKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import org.springframework.cassandra.core.keyspace.CreateIndexSpecification;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.DropIndexSpecification;
import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
import org.springframework.cassandra.support.CassandraAccessor;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.dao.QueryTimeoutException;
import org.springframework.util.Assert;
@@ -87,6 +104,11 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
return doExecute(sessionCallback);
}
@Override
public void execute(Query query) throws DataAccessException {
doExecute(query, null);
}
@Override
public void execute(final String cql) throws DataAccessException {
doExecute(cql, null);
@@ -278,6 +300,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
process(doExecute(cql, options), rch);
}
@Override
public void query(String cql, RowCallbackHandler rch) throws DataAccessException {
query(cql, rch, null);
}
@@ -287,26 +310,49 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
return process(doExecute(cql, options), rowMapper);
}
@Override
public ResultSet query(String cql) {
return query(cql, (QueryOptions) null);
}
@Override
public ResultSet query(String cql, QueryOptions options) {
return query(cql, new ResultSetExtractor<ResultSet>() {
@Override
public ResultSet extractData(ResultSet rs) throws DriverException, DataAccessException {
return rs;
}
}, options);
}
@Override
public <T> List<T> query(String cql, RowMapper<T> rowMapper) throws DataAccessException {
return query(cql, rowMapper, null);
}
@Override
public List<Map<String, Object>> queryForListOfMap(String cql) throws DataAccessException {
return processListOfMap(doExecute(cql, null));
}
@Override
public <T> List<T> queryForList(String cql, Class<T> elementType) throws DataAccessException {
return processList(doExecute(cql, null), elementType);
}
@Override
public Map<String, Object> queryForMap(String cql) throws DataAccessException {
return processMap(doExecute(cql, null));
}
@Override
public <T> T queryForObject(String cql, Class<T> requiredType) throws DataAccessException {
return processOne(doExecute(cql, null), requiredType);
}
@Override
public <T> T queryForObject(String cql, RowMapper<T> rowMapper) throws DataAccessException {
return processOne(doExecute(cql, null), rowMapper);
}
@@ -357,14 +403,14 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
* @param callback
* @return
*/
protected ResultSet doExecute(final BoundStatement bs, final QueryOptions options) {
protected ResultSet doExecute(final Query q, final QueryOptions options) {
return doExecute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
addQueryOptions(bs, options);
return s.execute(bs);
addQueryOptions(q, options);
return s.execute(q);
}
});
}
@@ -411,7 +457,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
*
* @return
*/
private Set<Host> getHosts() {
protected Set<Host> getHosts() {
/*
* Get the cluster metadata for this session
@@ -450,6 +496,16 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
});
}
@Override
public void executeAsynchronously(final Query query) throws DataAccessException {
execute(new SessionCallback<Object>() {
@Override
public Object doInSession(Session s) throws DataAccessException {
return s.executeAsync(query);
}
});
}
@Override
public void process(ResultSet resultSet, RowCallbackHandler rch) throws DataAccessException {
try {
@@ -766,6 +822,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
logger.debug("Executing prepared CQL query");
return execute(psc, new PreparedStatementCallback<T>() {
@Override
public T doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
@@ -794,6 +851,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
logger.debug("Executing prepared CQL query");
execute(psc, new PreparedStatementCallback<Object>() {
@Override
public Object doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
@@ -822,6 +880,7 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
logger.debug("Executing prepared CQL query");
return execute(psc, new PreparedStatementCallback<List<T>>() {
@Override
public List<T> doInPreparedStatement(PreparedStatement ps) throws DriverException {
ResultSet rs = null;
BoundStatement bs = null;
@@ -843,4 +902,121 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
return query(psc, psb, rowMapper, null);
}
@Override
public ResultSet execute(final DropTableSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(DropTableCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final CreateTableSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(CreateTableCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final AlterTableSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(AlterTableCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final DropKeyspaceSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(DropKeyspaceCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final CreateKeyspaceSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(CreateKeyspaceCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final AlterKeyspaceSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(AlterKeyspaceCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final DropIndexSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(DropIndexCqlGenerator.toCql(specification));
}
});
}
@Override
public ResultSet execute(final CreateIndexSpecification specification) {
return execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) throws DataAccessException {
return s.execute(CreateIndexCqlGenerator.toCql(specification));
}
});
}
@Override
public long count(String tableName) {
return selectCount(QueryBuilder.select().countAll().from(tableName).getQueryString());
}
protected long selectCount(String countQuery) {
return query(countQuery, new ResultSetExtractor<Long>() {
@Override
public Long extractData(ResultSet rs) throws DriverException, DataAccessException {
Row row = rs.one();
if (row == null) {
throw new InvalidDataAccessApiUsageException(String.format("count query did not return any results"));
}
return row.getLong(0);
}
});
}
}

View File

@@ -17,6 +17,8 @@ package org.springframework.cassandra.core.cql;
import java.util.regex.Pattern;
import com.datastax.driver.core.DataType;
public class CqlStringUtils {
protected static final String SINGLE_QUOTE = "\'";
@@ -24,6 +26,8 @@ public class CqlStringUtils {
protected static final String DOUBLE_QUOTE = "\"";
protected static final String DOUBLE_DOUBLE_QUOTE = "\"\"";
protected static final String EMPTY_STRING = "";
protected static final String TYPE_PARAMETER_PREFIX = "<";
protected static final String TYPE_PARAMETER_SUFFIX = ">";
public static StringBuilder noNull(StringBuilder sb) {
return sb == null ? new StringBuilder() : sb;
@@ -137,4 +141,34 @@ public class CqlStringUtils {
public static String removeSingleQuotes(Object thing) {
return thing == null ? (String) null : ((String) thing).replaceAll(SINGLE_QUOTE, EMPTY_STRING);
}
/**
* Renders the given {@link DataType} as a CQL string.
*
* @param dataType The {@link DataType} to render; must not be null.
*/
public static String toCql(DataType dataType) {
if (dataType.getTypeArguments().isEmpty()) {
return dataType.getName().name();
}
StringBuilder s = new StringBuilder();
s.append(dataType.getName().name()).append(TYPE_PARAMETER_PREFIX);
boolean first = true;
for (DataType argDataType : dataType.getTypeArguments()) {
if (first) {
first = false;
} else {
s.append(',');
}
s.append(argDataType.getName().name());
}
return s.append(TYPE_PARAMETER_SUFFIX).toString();
}
}

View File

@@ -29,10 +29,15 @@ import org.springframework.cassandra.core.keyspace.Option;
*/
public class AlterKeyspaceCqlGenerator extends KeyspaceOptionsCqlGenerator<AlterKeyspaceSpecification> {
public static String toCql(AlterKeyspaceSpecification specification) {
return new AlterKeyspaceCqlGenerator(specification).toCql();
}
public AlterKeyspaceCqlGenerator(AlterKeyspaceSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);

View File

@@ -34,10 +34,15 @@ import org.springframework.cassandra.core.keyspace.TableOption;
*/
public class AlterTableCqlGenerator extends TableOptionsCqlGenerator<AlterTableSpecification> {
public static String toCql(AlterTableSpecification specification) {
return new AlterTableCqlGenerator(specification).toCql();
}
public AlterTableCqlGenerator(AlterTableSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);

View File

@@ -28,10 +28,15 @@ import org.springframework.util.StringUtils;
*/
public class CreateIndexCqlGenerator extends IndexNameCqlGenerator<CreateIndexSpecification> {
public static String toCql(CreateIndexSpecification specification) {
return new CreateIndexCqlGenerator(specification).toCql();
}
public CreateIndexCqlGenerator(CreateIndexSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);

View File

@@ -32,10 +32,15 @@ import org.springframework.cassandra.core.keyspace.Option;
*/
public class CreateKeyspaceCqlGenerator extends KeyspaceCqlGenerator<CreateKeyspaceSpecification> {
public static String toCql(CreateKeyspaceSpecification specification) {
return new CreateKeyspaceCqlGenerator(specification).toCql();
}
public CreateKeyspaceCqlGenerator(CreateKeyspaceSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);

View File

@@ -35,10 +35,15 @@ import org.springframework.cassandra.core.keyspace.Option;
*/
public class CreateTableCqlGenerator extends TableCqlGenerator<CreateTableSpecification> {
public static String toCql(CreateTableSpecification specification) {
return new CreateTableCqlGenerator(specification).toCql();
}
public CreateTableCqlGenerator(CreateTableSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
cql = noNull(cql);

View File

@@ -27,10 +27,15 @@ import org.springframework.cassandra.core.keyspace.DropIndexSpecification;
*/
public class DropIndexCqlGenerator extends IndexNameCqlGenerator<DropIndexSpecification> {
public static String toCql(DropIndexSpecification specification) {
return new DropIndexCqlGenerator(specification).toCql();
}
public DropIndexCqlGenerator(DropIndexSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP INDEX ")
// .append(spec().getIfExists() ? "IF EXISTS " : "")

View File

@@ -26,10 +26,15 @@ import org.springframework.cassandra.core.keyspace.DropKeyspaceSpecification;
*/
public class DropKeyspaceCqlGenerator extends KeyspaceNameCqlGenerator<DropKeyspaceSpecification> {
public static String toCql(DropKeyspaceSpecification specification) {
return new DropKeyspaceCqlGenerator(specification).toCql();
}
public DropKeyspaceCqlGenerator(DropKeyspaceSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP KEYSPACE ").append(spec().getIfExists() ? "IF EXISTS " : "")
.append(spec().getNameAsIdentifier()).append(";");

View File

@@ -26,10 +26,15 @@ import org.springframework.cassandra.core.keyspace.DropTableSpecification;
*/
public class DropTableCqlGenerator extends TableNameCqlGenerator<DropTableSpecification> {
public static String toCql(DropTableSpecification specification) {
return new DropTableCqlGenerator(specification).toCql();
}
public DropTableCqlGenerator(DropTableSpecification specification) {
super(specification);
}
@Override
public StringBuilder toCql(StringBuilder cql) {
return noNull(cql).append("DROP TABLE ")
// .append(spec().getIfExists() ? "IF EXISTS " : "")

View File

@@ -47,6 +47,11 @@ public class CreateTableSpecification extends TableSpecification<CreateTableSpec
return ifNotExists;
}
@Override
public CreateTableSpecification name(String name) {
return (CreateTableSpecification) super.name(name);
}
/**
* Entry point into the {@link CreateTableSpecification}'s fluent API to create a table. Convenient if imported
* statically.

View File

@@ -46,4 +46,15 @@ public class DropTableSpecification extends TableNameSpecification<DropTableSpec
public static DropTableSpecification dropTable() {
return new DropTableSpecification();
}
/**
* Entry point into the {@link DropTableSpecification}'s fluent API to drop a table. Convenient if imported
* statically. This static method is shorter than the no-arg form, which would be
* <code>dropTable().name(tableName)</code>.
*
* @param tableName The name of the table to drop.
*/
public static DropTableSpecification dropTable(String tableName) {
return new DropTableSpecification().name(tableName);
}
}

View File

@@ -0,0 +1,27 @@
package org.springframework.cassandra.core.util;
import java.util.ArrayList;
import java.util.List;
public class CollectionUtils {
@SuppressWarnings("unchecked")
public static <T> T[] toArray(Iterable<T> i) {
return (T[]) toList(i).toArray();
}
public static <T> List<T> toList(Iterable<T> i) {
List<T> list = null;
if (i instanceof List) {
list = (List<T>) i;
} else {
list = new ArrayList<T>();
for (T t : i) {
list.add(t);
}
}
return list;
}
}

View File

@@ -24,7 +24,6 @@ import com.datastax.driver.core.Session;
/**
* @author David Webb
*
*/
public class CassandraAccessor implements InitializingBean {
@@ -56,9 +55,7 @@ public class CassandraAccessor implements InitializingBean {
*/
@Override
public void afterPropertiesSet() {
if (getSession() == null) {
throw new IllegalArgumentException("Property 'session' is required");
}
Assert.notNull(session);
}
/**

View File

@@ -127,6 +127,12 @@
<scope>test</scope>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
<scope>test</scope>
</dependency>
</dependencies>
</project>

View File

@@ -7,6 +7,8 @@ import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.EntityMapping;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;

View File

@@ -15,6 +15,7 @@
*/
package org.springframework.data.cassandra.config.java;
import java.lang.annotation.Annotation;
import java.util.HashSet;
import java.util.Set;
@@ -27,7 +28,6 @@ import org.springframework.context.annotation.Configuration;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.data.annotation.Persistent;
import org.springframework.data.cassandra.config.CassandraDataSessionFactoryBean;
import org.springframework.data.cassandra.config.Mapping;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
@@ -35,6 +35,8 @@ import org.springframework.data.cassandra.core.CassandraAdminOperations;
import org.springframework.data.cassandra.core.CassandraAdminTemplate;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.util.ClassUtils;
@@ -66,7 +68,7 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
* The base package to scan for entities annotated with {@link Table} annotations. By default, returns the package
* name of {@literal this} (<code>this.getClass().getPackage().getName()</code>).
*/
public String getMappingBasePackage() {
public String getEntityBasePackage() {
return getClass().getPackage().getName();
}
@@ -125,13 +127,13 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
/**
* Scans the mapping base package for entity classes annotated with {@link Table} or {@link Persistent}.
*
* @see #getMappingBasePackage()
* @see #getEntityBasePackage()
* @return <code>Set&lt;Class&lt;?&gt;&gt;</code> representing the annotated entity classes found.
* @throws ClassNotFoundException
*/
protected Set<Class<?>> getInitialEntitySet() throws ClassNotFoundException {
String basePackage = getMappingBasePackage();
String basePackage = getEntityBasePackage();
Set<Class<?>> initialEntitySet = new HashSet<Class<?>>();
if (StringUtils.hasText(basePackage)) {
@@ -139,6 +141,7 @@ public abstract class AbstractSpringDataCassandraConfiguration extends AbstractC
false);
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Table.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(Persistent.class));
componentProvider.addIncludeFilter(new AnnotationTypeFilter(PrimaryKeyClass.class));
for (BeanDefinition candidate : componentProvider.findCandidateComponents(basePackage)) {

View File

@@ -10,9 +10,9 @@ import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.cassandra.config.xml.CassandraSessionParser;
import org.springframework.data.cassandra.config.DefaultDataBeanNames;
import org.springframework.data.cassandra.config.CassandraDataSessionFactoryBean;
import org.springframework.data.cassandra.config.EntityMapping;
import org.springframework.data.cassandra.config.Mapping;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.mapping.EntityMapping;
import org.springframework.data.cassandra.mapping.Mapping;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Attr;

View File

@@ -0,0 +1,15 @@
package org.springframework.data.cassandra.convert;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
import org.springframework.data.mapping.model.PropertyValueProvider;
public class CassandraPersistentEntityParameterValueProvider extends
PersistentEntityParameterValueProvider<CassandraPersistentProperty> {
public CassandraPersistentEntityParameterValueProvider(PersistentEntity<?, CassandraPersistentProperty> entity,
PropertyValueProvider<CassandraPersistentProperty> provider, Object parent) {
super(entity, provider, parent);
}
}

View File

@@ -31,11 +31,10 @@ import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.mapping.model.DefaultSpELExpressionEvaluator;
import org.springframework.data.mapping.model.MappingException;
import org.springframework.data.mapping.model.PersistentEntityParameterValueProvider;
import org.springframework.data.mapping.model.PropertyValueProvider;
import org.springframework.data.mapping.model.SpELContext;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.datastax.driver.core.Row;
@@ -54,14 +53,14 @@ import com.datastax.driver.core.querybuilder.Update;
public class MappingCassandraConverter extends AbstractCassandraConverter implements CassandraConverter,
ApplicationContextAware, BeanClassLoaderAware {
protected static final Logger log = LoggerFactory.getLogger(MappingCassandraConverter.class);
protected final Logger log = LoggerFactory.getLogger(getClass());
protected final CassandraMappingContext mappingContext;
protected ApplicationContext applicationContext;
private SpELContext spELContext;
private boolean useFieldAccessOnly = true;
protected SpELContext spELContext;
protected boolean useFieldAccessOnly = true;
private ClassLoader beanClassLoader;
protected ClassLoader beanClassLoader;
/**
* Creates a new {@link MappingCassandraConverter} with the given {@link CassandraMappingContext}.
@@ -69,7 +68,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
* @param mappingContext must not be {@literal null}.
*/
public MappingCassandraConverter(CassandraMappingContext mappingContext) {
super(new DefaultConversionService());
Assert.notNull(mappingContext);
this.mappingContext = mappingContext;
this.spELContext = new SpELContext(RowReaderPropertyAccessor.INSTANCE);
}
@@ -111,45 +114,48 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
final DefaultSpELExpressionEvaluator evaluator = new DefaultSpELExpressionEvaluator(row, spELContext);
final PropertyValueProvider<CassandraPersistentProperty> propertyProvider = new CassandraPropertyValueProvider(row,
evaluator);
final CassandraPropertyValueProvider propertyProvider = new CassandraPropertyValueProvider(row, evaluator);
PersistentEntityParameterValueProvider<CassandraPersistentProperty> parameterProvider = new PersistentEntityParameterValueProvider<CassandraPersistentProperty>(
CassandraPersistentEntityParameterValueProvider parameterProvider = new CassandraPersistentEntityParameterValueProvider(
entity, propertyProvider, null);
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
S instance = instantiator.createInstance(entity, parameterProvider);
final BeanWrapper<CassandraPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
S result = wrapper.getBean();
readPropertiesFromRow(entity, row, propertyProvider, wrapper);
return wrapper.getBean();
}
protected void readPropertiesFromRow(final CassandraPersistentEntity<?> entity, final Row row,
final CassandraPropertyValueProvider propertyProvider, final BeanWrapper<?, ?> wrapper) {
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
MappingCassandraConverter.this.handlePersistentPropertyRead(row, entity, prop, propertyProvider, wrapper);
MappingCassandraConverter.this.readPropertyFromRow(row, entity, prop, propertyProvider, wrapper);
}
});
return result;
}
protected void handlePersistentPropertyRead(final Row row, final CassandraPersistentEntity<?> entity,
final CassandraPersistentProperty prop,
final PropertyValueProvider<CassandraPersistentProperty> propertyProvider, final BeanWrapper<?, ?> wrapper) {
protected void readPropertyFromRow(final Row row, final CassandraPersistentEntity<?> entity,
final CassandraPersistentProperty prop, final CassandraPropertyValueProvider propertyProvider,
final BeanWrapper<?, ?> wrapper) {
if (entity.isConstructorArgument(prop)) { // skip 'cause prop was set in ctor
return;
}
if (prop.isCompositePrimaryKey()) {
// handle composite primary key properties via recursion into this method
throw new UnsupportedOperationException("composite primary keys are TODO");
readPropertiesFromRow(prop.getCompositePrimaryKeyEntity(), row, propertyProvider, wrapper);
return;
}
boolean hasValueForProperty = row.getColumnDefinitions().contains(prop.getColumnName());
if (!hasValueForProperty) {
if (!row.getColumnDefinitions().contains(prop.getColumnName())) {
return;
}
@@ -174,103 +180,121 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
}
@Override
public void write(Object obj, Object builtStatement) {
public void write(Object source, Object sink) {
if (obj == null) {
if (source == null) {
return;
}
Class<?> beanClassLoaderClass = transformClassToBeanClassLoaderClass(obj.getClass());
Class<?> beanClassLoaderClass = transformClassToBeanClassLoaderClass(source.getClass());
CassandraPersistentEntity<?> entity = mappingContext.getPersistentEntity(beanClassLoaderClass);
if (entity == null) {
throw new MappingException("No mapping metadata found for " + obj.getClass());
throw new MappingException("No mapping metadata found for " + source.getClass());
}
if (builtStatement instanceof Insert) {
writeInsertInternal(obj, (Insert) builtStatement, entity);
} else if (builtStatement instanceof Update) {
writeUpdateInternal(obj, (Update) builtStatement, entity);
} else if (builtStatement instanceof Where) {
writeDeleteWhereInternal(obj, (Where) builtStatement, entity);
if (sink instanceof Insert) {
writeInsertFromObject(source, (Insert) sink, entity);
} else if (sink instanceof Update) {
writeUpdateFromObject(source, (Update) sink, entity);
} else if (sink instanceof Where) {
writeDeleteWhereFromObject(source, (Where) sink, entity);
} else {
throw new MappingException("Unknown buildStatement " + builtStatement.getClass().getName());
throw new MappingException("Unknown buildStatement " + sink.getClass().getName());
}
}
private void writeInsertInternal(final Object objectToSave, final Insert insert, CassandraPersistentEntity<?> entity) {
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
insert.value(prop.getColumnName(), propertyObj);
}
}
});
protected void writeInsertFromObject(final Object object, final Insert insert, CassandraPersistentEntity<?> entity) {
writeInsertFromWrapper(BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService),
insert, entity);
}
private void writeUpdateInternal(final Object objectToSave, final Update update, CassandraPersistentEntity<?> entity) {
protected void writeInsertFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
final Insert insert, CassandraPersistentEntity<?> entity) {
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
Object value = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
if (prop.isIdProperty()) {
update.where(QueryBuilder.eq(prop.getColumnName(), propertyObj));
if (prop.isCompositePrimaryKey()) {
writeInsertFromWrapper(
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(value, conversionService), insert,
prop.getCompositePrimaryKeyEntity());
return;
}
if (value != null) {
insert.value(prop.getColumnName(), value);
}
}
});
}
protected void writeUpdateFromObject(final Object object, final Update update, CassandraPersistentEntity<?> entity) {
writeUpdateFromWrapper(BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService),
update, entity);
}
protected void writeUpdateFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
final Update update, final CassandraPersistentEntity<?> entity) {
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
Object value = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (prop.isCompositePrimaryKey()) {
writeUpdateFromWrapper(
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(value, conversionService), update,
prop.getCompositePrimaryKeyEntity());
return;
}
if (value != null) {
if (prop.isIdProperty() || entity.isCompositePrimaryKey()) {
update.where(QueryBuilder.eq(prop.getColumnName(), value));
} else {
update.with(QueryBuilder.set(prop.getColumnName(), propertyObj));
update.with(QueryBuilder.set(prop.getColumnName(), value));
}
}
}
});
}
private void writeDeleteWhereInternal(final Object objectToSave, final Where whereId,
CassandraPersistentEntity<?> entity) {
protected void writeDeleteWhereFromObject(final Object object, final Where where, CassandraPersistentEntity<?> entity) {
writeDeleteWhereFromWrapper(
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService), where, entity);
}
final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper = BeanWrapper.create(objectToSave,
conversionService);
protected void writeDeleteWhereFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
final Where where, CassandraPersistentEntity<?> entity) {
// Write the properties
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
CassandraPersistentProperty idProperty = entity.getIdProperty();
Object idValue = wrapper.getProperty(idProperty, idProperty.getType(), useFieldAccessOnly);
if (prop.isIdProperty()) {
if (idValue == null) {
String msg = String.format("no id value found in object {}", wrapper.getBean());
log.error(msg);
throw new IllegalArgumentException(msg);
}
Object propertyObj = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
if (propertyObj != null) {
whereId.and(QueryBuilder.eq(prop.getColumnName(), propertyObj));
}
}
}
});
if (idProperty.isCompositePrimaryKey()) {
writeDeleteWhereFromWrapper(
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(idValue, conversionService), where,
idProperty.getCompositePrimaryKeyEntity());
return;
}
where.and(QueryBuilder.eq(idProperty.getColumnName(), idValue));
}
@SuppressWarnings("unchecked")
private <T> Class<T> transformClassToBeanClassLoaderClass(Class<T> entity) {
protected <T> Class<T> transformClassToBeanClassLoaderClass(Class<T> entity) {
try {
return (Class<T>) ClassUtils.forName(entity.getName(), beanClassLoader);
} catch (ClassNotFoundException e) {

View File

@@ -6,7 +6,12 @@ import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.cassandra.core.SessionCallback;
import org.springframework.cassandra.core.cql.generator.AlterTableCqlGenerator;
import org.springframework.cassandra.core.cql.generator.CreateTableCqlGenerator;
import org.springframework.cassandra.core.cql.generator.DropTableCqlGenerator;
import org.springframework.cassandra.core.keyspace.AlterTableSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.cassandra.core.keyspace.DropTableSpecification;
import org.springframework.dao.DataAccessException;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.cassandra.convert.CassandraConverter;
@@ -60,7 +65,9 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
@Override
public void replaceTable(String tableName, Class<?> entityClass, Map<String, Object> optionsByName) {
throw new UnsupportedOperationException("not yet implemented");
dropTable(tableName);
createTable(false, tableName, entityClass, optionsByName);
}
/**
@@ -102,15 +109,7 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
log.info("Dropping table => " + tableName);
final String q = CqlUtils.dropTable(tableName);
log.info(q);
execute(new SessionCallback<ResultSet>() {
@Override
public ResultSet doInSession(Session s) {
return s.execute(q);
}
});
execute(DropTableSpecification.dropTable(tableName));
}
@Override
@@ -125,24 +124,4 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
}
});
}
/**
* @param entityClass
* @return
*/
@Override
public String determineTableName(Class<?> entityClass) {
if (entityClass == null) {
throw new InvalidDataAccessApiUsageException(
"No class parameter provided, entity table name can't be determined!");
}
CassandraPersistentEntity<?> entity = getCassandraMappingContext().getPersistentEntity(entityClass);
if (entity == null) {
throw new InvalidDataAccessApiUsageException("No Persitent Entity information found for the class "
+ entityClass.getName());
}
return entity.getTableName();
}
}

View File

@@ -16,32 +16,34 @@
package org.springframework.data.cassandra.core;
import org.springframework.cassandra.core.RowCallback;
import org.springframework.data.convert.EntityReader;
import org.springframework.data.cassandra.convert.CassandraConverter;
import org.springframework.util.Assert;
import com.datastax.driver.core.Row;
/**
* Simple {@link RowCallback} that will transform {@link Row} into the given target type using the given
* {@link EntityReader}.
* Simple {@link RowCallback} that will transform a {@link Row} into the given target type using the given
* {@link CassandraConverter}.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public class ReadRowCallback<T> implements RowCallback<T> {
public class CassandraConverterRowCallback<T> implements RowCallback<T> {
private final EntityReader<? super T, Object> reader;
private final CassandraConverter reader;
private final Class<T> type;
public ReadRowCallback(EntityReader<? super T, Object> reader, Class<T> type) {
public CassandraConverterRowCallback(CassandraConverter reader, Class<T> type) {
Assert.notNull(reader);
Assert.notNull(type);
this.reader = reader;
this.type = type;
}
@Override
public T doWith(Row row) {
T source = reader.read(type, row);
return source;
return reader.read(type, row);
}
}

View File

@@ -21,8 +21,6 @@ import org.springframework.cassandra.core.CqlOperations;
import org.springframework.cassandra.core.QueryOptions;
import org.springframework.data.cassandra.convert.CassandraConverter;
import com.datastax.driver.core.querybuilder.Select;
/**
* Operations for interacting with Cassandra. These operations are used by the Repository implementation, but can also
* be used directly when that is desired by the developer.
@@ -30,7 +28,6 @@ import com.datastax.driver.core.querybuilder.Select;
* @author Alex Shvid
* @author David Webb
* @author Matthew Adams
*
*/
public interface CassandraOperations extends CqlOperations {
@@ -46,49 +43,25 @@ public interface CassandraOperations extends CqlOperations {
* Execute query and convert ResultSet to the list of entities
*
* @param query must not be {@literal null}.
* @param selectClass must not be {@literal null}, mapped entity type.
* @param type must not be {@literal null}, mapped entity type.
* @return
*/
<T> List<T> select(String cql, Class<T> selectClass);
<T> List<T> select(String cql, Class<T> type);
/**
* Execute query and convert ResultSet to the list of entities
*
* @param selectQuery must not be {@literal null}.
* @param selectClass must not be {@literal null}, mapped entity type.
* @return
*/
<T> List<T> select(Select selectQuery, Class<T> selectClass);
<T> T selectOneById(Class<T> type, Object id);
/**
* Execute query and convert ResultSet to the entity
*
* @param query must not be {@literal null}.
* @param selectClass must not be {@literal null}, mapped entity type.
* @param type must not be {@literal null}, mapped entity type.
* @return
*/
<T> T selectOne(String cql, Class<T> selectClass);
<T> T selectOne(String cql, Class<T> type);
<T> T selectOne(Select selectQuery, Class<T> selectClass);
boolean exists(Class<?> type, Object id);
/**
* Counts rows for given query
*
* @param selectQuery
* @return
*/
Long count(Select selectQuery);
/**
* Counts all rows for given table
*
* @param tableName
* @return
*/
Long count(String tableName);
long count(Class<?> type);
/**
* Insert the given object to the table by id.
@@ -97,23 +70,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T insert(T entity);
/**
* Insert the given object to the table by id.
*
* @param entity
* @param tableName
* @return
*/
<T> T insert(T entity, String tableName);
/**
* @param entity
* @param tableName
* @param options
* @return
*/
<T> T insert(T entity, String tableName, QueryOptions options);
/**
* @param entity
* @param tableName
@@ -130,15 +86,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> insert(List<T> entities);
/**
* Insert the given list of objects to the table by name.
*
* @param entities
* @param tableName
* @return
*/
<T> List<T> insert(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -147,14 +94,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> insert(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
* @return
*/
<T> List<T> insert(List<T> entities, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -162,13 +101,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T insertAsynchronously(T entity);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> T insertAsynchronously(T entity, String tableName);
/**
* @param entity
* @param tableName
@@ -177,14 +109,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T insertAsynchronously(T entity, QueryOptions options);
/**
* @param entity
* @param tableName
* @param options
* @return
*/
<T> T insertAsynchronously(T entity, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -192,13 +116,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> insertAsynchronously(List<T> entities);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> List<T> insertAsynchronously(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -207,14 +124,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> insertAsynchronously(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
* @return
*/
<T> List<T> insertAsynchronously(List<T> entities, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -222,13 +131,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T update(T entity);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> T update(T entity, String tableName);
/**
* @param entity
* @param tableName
@@ -237,14 +139,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T update(T entity, QueryOptions options);
/**
* @param entity
* @param tableName
* @param options
* @return
*/
<T> T update(T entity, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -252,13 +146,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> update(List<T> entities);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> List<T> update(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -267,14 +154,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> update(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
* @return
*/
<T> List<T> update(List<T> entities, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -282,13 +161,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T updateAsynchronously(T entity);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> T updateAsynchronously(T entity, String tableName);
/**
* @param entity
* @param tableName
@@ -297,14 +169,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> T updateAsynchronously(T entity, QueryOptions options);
/**
* @param entity
* @param tableName
* @param options
* @return
*/
<T> T updateAsynchronously(T entity, String tableName, QueryOptions options);
/**
* Insert the given object to the table by id.
*
@@ -312,13 +176,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> updateAsynchronously(List<T> entities);
/**
* Insert the given object to the table by id.
*
* @param object
*/
<T> List<T> updateAsynchronously(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -327,14 +184,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> List<T> updateAsynchronously(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
* @return
*/
<T> List<T> updateAsynchronously(List<T> entities, String tableName, QueryOptions options);
/**
* Remove the given object from the table by id.
*
@@ -342,14 +191,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void delete(T entity);
/**
* Removes the given object from the given table.
*
* @param object
* @param table must not be {@literal null} or empty.
*/
<T> void delete(T entity, String tableName);
/**
* @param entity
* @param tableName
@@ -357,13 +198,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void delete(T entity, QueryOptions options);
/**
* @param entity
* @param tableName
* @param options
*/
<T> void delete(T entity, String tableName, QueryOptions options);
/**
* Remove the given object from the table by id.
*
@@ -371,14 +205,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void delete(List<T> entities);
/**
* Removes the given object from the given table.
*
* @param object
* @param table must not be {@literal null} or empty.
*/
<T> void delete(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -386,13 +212,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void delete(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
*/
<T> void delete(List<T> entities, String tableName, QueryOptions options);
/**
* Remove the given object from the table by id.
*
@@ -407,21 +226,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void deleteAsynchronously(T entity, QueryOptions options);
/**
* @param entity
* @param tableName
* @param options
*/
<T> void deleteAsynchronously(T entity, String tableName, QueryOptions options);
/**
* Removes the given object from the given table.
*
* @param object
* @param table must not be {@literal null} or empty.
*/
<T> void deleteAsynchronously(T entity, String tableName);
/**
* Remove the given object from the table by id.
*
@@ -429,14 +233,6 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void deleteAsynchronously(List<T> entities);
/**
* Removes the given object from the given table.
*
* @param object
* @param table must not be {@literal null} or empty.
*/
<T> void deleteAsynchronously(List<T> entities, String tableName);
/**
* @param entities
* @param tableName
@@ -444,17 +240,16 @@ public interface CassandraOperations extends CqlOperations {
*/
<T> void deleteAsynchronously(List<T> entities, QueryOptions options);
/**
* @param entities
* @param tableName
* @param options
*/
<T> void deleteAsynchronously(List<T> entities, String tableName, QueryOptions options);
/**
* Returns the underlying {@link CassandraConverter}.
*
* @return
*/
CassandraConverter getConverter();
void deleteById(Class<?> type, Object id);
<T> List<T> selectBySimpleIds(Class<T> type, Iterable<?> ids);
<T> List<T> selectAll(Class<T> type);
}

View File

@@ -1,50 +0,0 @@
/*
* Copyright 2011-2013 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.exception;
/**
* Exception to handle failing to write a PersistedEntity to a CQL String or Query object
*
* @author David Webb
*
*/
public class EntityWriterException extends Exception {
private static final long serialVersionUID = -3068204776019978031L;
/**
* @param message
*/
public EntityWriterException(String message) {
super(message);
}
/**
* @param cause
*/
public EntityWriterException(Throwable cause) {
super(cause);
}
/**
* @param message
* @param cause
*/
public EntityWriterException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.cassandra.mapping;
import java.util.ArrayList;
import java.util.List;
import org.springframework.beans.BeansException;
import org.springframework.cassandra.support.exception.UnsupportedCassandraOperationException;
import org.springframework.context.ApplicationContext;
@@ -24,6 +27,7 @@ import org.springframework.context.expression.BeanFactoryResolver;
import org.springframework.data.cassandra.util.CassandraNamingUtils;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.AssociationHandler;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.BasicPersistentEntity;
import org.springframework.data.util.TypeInformation;
import org.springframework.expression.Expression;
@@ -34,8 +38,7 @@ import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* Cassandra specific {@link BasicPersistentEntity} implementation that adds Cassandra specific metadata such as the
* table name.
* Cassandra specific {@link BasicPersistentEntity} implementation that adds Cassandra specific metadata.
*
* @author Alex Shvid
* @author Matthew T. Adams
@@ -43,10 +46,14 @@ import org.springframework.util.StringUtils;
public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T, CassandraPersistentProperty> implements
CassandraPersistentEntity<T>, ApplicationContextAware {
private String tableName;
private final SpelExpressionParser spelParser;
private final StandardEvaluationContext spelContext;
private final Class<T> type;
protected String tableName;
protected CassandraMappingContext mappingContext;
protected final SpelExpressionParser spelParser;
protected final StandardEvaluationContext spelContext;
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation) {
this(typeInformation, null);
}
/**
* Creates a new {@link BasicCassandraPersistentEntity} with the given {@link TypeInformation}. Will default the table
@@ -54,23 +61,22 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
*
* @param typeInformation
*/
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation) {
public BasicCassandraPersistentEntity(TypeInformation<T> typeInformation, CassandraMappingContext mappingContext) {
super(typeInformation, DefaultCassandraPersistentPropertyColumnComparator.IT);
super(typeInformation, CassandraPersistentPropertyComparator.IT);
this.spelParser = new SpelExpressionParser();
this.spelContext = new StandardEvaluationContext();
this.type = typeInformation.getType();
this.mappingContext = mappingContext;
determineTableName();
}
protected void determineTableName() {
Table anno = type.getAnnotation(Table.class);
Table anno = getType().getAnnotation(Table.class);
this.tableName = anno != null && StringUtils.hasText(anno.value()) ? anno.value() : CassandraNamingUtils
.getPreferredTableName(type);
.getPreferredTableName(getType());
}
@Override
@@ -102,4 +108,46 @@ public class BasicCassandraPersistentEntity<T> extends BasicPersistentEntity<T,
Assert.hasText(tableName);
this.tableName = tableName;
}
@Override
public CassandraMappingContext getMappingContext() {
return mappingContext;
}
@Override
public boolean isCompositePrimaryKey() {
return getType().isAnnotationPresent(PrimaryKeyClass.class);
}
@Override
public List<CassandraPersistentProperty> getCompositePrimaryKeyProperties() {
final List<CassandraPersistentProperty> properties = new ArrayList<CassandraPersistentProperty>();
if (!isCompositePrimaryKey()) {
throw new IllegalStateException(String.format("[%s] does not represent a composite primary key class", this
.getType().getName()));
}
addCompositePrimaryKeyProperties(this, properties);
return properties;
}
protected void addCompositePrimaryKeyProperties(CassandraPersistentEntity<?> compositePrimaryKeyEntity,
final List<CassandraPersistentProperty> properties) {
compositePrimaryKeyEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty p) {
if (p.isCompositePrimaryKey()) {
addCompositePrimaryKeyProperties(p.getCompositePrimaryKeyEntity(), properties);
} else {
properties.add(p);
}
}
});
}
}

View File

@@ -17,6 +17,7 @@ package org.springframework.data.cassandra.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
@@ -24,6 +25,7 @@ import org.springframework.cassandra.core.Ordering;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.dao.InvalidDataAccessApiUsageException;
import org.springframework.data.mapping.Association;
import org.springframework.data.mapping.PropertyHandler;
import org.springframework.data.mapping.model.AnnotationBasedPersistentProperty;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.data.util.TypeInformation;
@@ -49,15 +51,20 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
*/
public BasicCassandraPersistentProperty(Field field, PropertyDescriptor propertyDescriptor,
CassandraPersistentEntity<?> owner, CassandraSimpleTypeHolder simpleTypeHolder) {
super(field, propertyDescriptor, owner, simpleTypeHolder);
}
@Override
public CassandraPersistentEntity<?> getOwner() {
return (CassandraPersistentEntity<?>) super.getOwner();
}
@Override
public boolean isCompositePrimaryKey() {
return getField().getType().isAnnotationPresent(PrimaryKeyClass.class);
}
@Override
public Class<?> getCompositePrimaryKeyType() {
if (!isCompositePrimaryKey()) {
return null;
@@ -67,31 +74,23 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
}
@Override
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
public TypeInformation<?> getCompositePrimaryKeyTypeInformation() {
if (!isCompositePrimaryKey()) {
return null;
}
return (CassandraPersistentEntity<?>) ClassTypeInformation.from(getCompositePrimaryKeyType());
return ClassTypeInformation.from(getCompositePrimaryKeyType());
}
@Override
public String getColumnName() {
// first check @Column annotation
Column column = findAnnotation(Column.class);
if (column != null && StringUtils.hasText(column.value())) {
return column.value();
List<String> columnNames = getColumnNames();
if (columnNames.size() != 1) {
throw new IllegalStateException("property does not have a single column mapping");
}
// else check @PrimaryKeyColumn annotation
PrimaryKeyColumn pk = findAnnotation(PrimaryKeyColumn.class);
if (pk != null && StringUtils.hasText(pk.name())) {
return pk.name();
}
// else default
return field.getName().toLowerCase(); // TODO: replace with naming strategy class
return columnNames.get(0);
}
@Override
@@ -199,11 +198,6 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
return isAnnotationPresent(PrimaryKeyColumn.class);
}
@Override
protected Association<CassandraPersistentProperty> createAssociation() {
return new Association<CassandraPersistentProperty>(this, null);
}
protected DataType getDataTypeFor(DataType.Name typeName) {
DataType dataType = CassandraSimpleTypeHolder.getDataTypeFor(typeName);
if (dataType == null) {
@@ -230,4 +224,79 @@ public class BasicCassandraPersistentProperty extends AnnotationBasedPersistentP
+ this.getName() + "' type is '" + this.getType() + "' in the entity " + this.getOwner().getName());
}
}
@Override
public List<String> getColumnNames() {
final List<String> columnNames = new ArrayList<String>();
if (isCompositePrimaryKey()) {
addCompositePrimaryKeyColumnNames(getCompositePrimaryKeyEntity(), columnNames);
return columnNames;
}
// else not a composite primary key property -- first check @Column annotation
Column column = findAnnotation(Column.class);
if (column != null && StringUtils.hasText(column.value())) {
columnNames.add(column.value());
return columnNames;
}
// else check @PrimaryKeyColumn annotation
PrimaryKeyColumn pk = findAnnotation(PrimaryKeyColumn.class);
if (pk != null && StringUtils.hasText(pk.name())) {
columnNames.add(pk.name());
return columnNames;
}
// else default
columnNames.add(field.getName().toLowerCase()); // TODO: replace with naming strategy class
return columnNames;
}
protected void addCompositePrimaryKeyColumnNames(CassandraPersistentEntity<?> compositePrimaryKeyEntity,
final List<String> columnNames) {
compositePrimaryKeyEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty p) {
if (p.isCompositePrimaryKey()) {
addCompositePrimaryKeyColumnNames(p.getCompositePrimaryKeyEntity(), columnNames);
} else {
columnNames.add(p.getColumnName());
}
}
});
}
@Override
public List<CassandraPersistentProperty> getCompositePrimaryKeyProperties() {
if (!isCompositePrimaryKey()) {
throw new IllegalStateException(String.format("[%s] does not represent a composite primary key property",
getField()));
}
return getCompositePrimaryKeyEntity().getCompositePrimaryKeyProperties();
}
@Override
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
CassandraMappingContext mappingContext = getOwner().getMappingContext();
if (mappingContext == null) {
throw new IllegalStateException("need CassandraMappingContext");
}
return mappingContext.getPersistentEntity(getCompositePrimaryKeyTypeInformation());
}
@Override
public Association<CassandraPersistentProperty> getAssociation() {
throw new UnsupportedOperationException("Cassandra does not support associations");
}
@Override
protected Association<CassandraPersistentProperty> createAssociation() {
return new Association<CassandraPersistentProperty>(this, null);
}
}

View File

@@ -0,0 +1,64 @@
package org.springframework.data.cassandra.mapping;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.springframework.data.util.TypeInformation;
public class CachingCassandraPersistentEntity<T> extends BasicCassandraPersistentEntity<T> {
protected String tableName;
protected String name;
protected Boolean isCompositePrimaryKey;
protected List<CassandraPersistentProperty> compositePrimaryKeyProperties;
protected Map<String, CassandraPersistentProperty> properties = new HashMap<String, CassandraPersistentProperty>();
public CachingCassandraPersistentEntity(TypeInformation<T> typeInformation) {
super(typeInformation);
}
public CachingCassandraPersistentEntity(TypeInformation<T> typeInformation, CassandraMappingContext mappingContext) {
super(typeInformation, mappingContext);
}
@Override
public String getTableName() {
if (tableName == null) {
tableName = super.getTableName();
}
return tableName;
}
@Override
public String getName() {
if (name == null) {
name = super.getName();
}
return name;
}
@Override
public boolean isCompositePrimaryKey() {
if (isCompositePrimaryKey == null) {
isCompositePrimaryKey = super.isCompositePrimaryKey();
}
return isCompositePrimaryKey;
}
@Override
public List<CassandraPersistentProperty> getCompositePrimaryKeyProperties() {
if (compositePrimaryKeyProperties == null) {
compositePrimaryKeyProperties = super.getCompositePrimaryKeyProperties();
}
return compositePrimaryKeyProperties;
}
@Override
public CassandraPersistentProperty getPersistentProperty(String name) {
if (properties.get(name) == null) {
properties.put(name, super.getPersistentProperty(name));
}
return properties.get(name);
}
}

View File

@@ -17,8 +17,10 @@ package org.springframework.data.cassandra.mapping;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.List;
import org.springframework.cassandra.core.Ordering;
import org.springframework.data.util.TypeInformation;
import com.datastax.driver.core.DataType;
@@ -37,11 +39,12 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
private Boolean isClusterKeyColumn;
private Boolean isPrimaryKeyColumn;
private String columnName;
private List<String> columnNames;
private Ordering ordering;
private boolean orderingCached = false;
private DataType dataType;
private Class<?> compositePrimaryKeyType;
private CassandraPersistentEntity<?> compositePrimaryKeyEntity;
private TypeInformation<?> compositePrimaryKeyTypeInformation;
/**
* Creates a new {@link CachingCassandraPersistentProperty}.
@@ -52,12 +55,12 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
}
@Override
public CassandraPersistentEntity<?> getCompositePrimaryKeyEntity() {
public TypeInformation<?> getCompositePrimaryKeyTypeInformation() {
if (compositePrimaryKeyEntity == null) {
compositePrimaryKeyEntity = super.getCompositePrimaryKeyEntity();
if (compositePrimaryKeyTypeInformation == null) {
compositePrimaryKeyTypeInformation = super.getCompositePrimaryKeyTypeInformation();
}
return compositePrimaryKeyEntity;
return compositePrimaryKeyTypeInformation;
}
@Override
@@ -150,4 +153,12 @@ public class CachingCassandraPersistentProperty extends BasicCassandraPersistent
}
return isPartitionKeyColumn;
}
@Override
public List<String> getColumnNames() {
if (columnNames == null) {
columnNames = super.getColumnNames();
}
return columnNames;
}
}

View File

@@ -0,0 +1,21 @@
package org.springframework.data.cassandra.mapping;
import java.util.Comparator;
/**
* {@link Comparator} implementation that uses {@link Column#value()}.
*
* @author Matthew T. Adams
*/
public enum CassandraColumnAnnotationComparator implements Comparator<Column> {
/**
* The sole instance of this class.
*/
IT;
@Override
public int compare(Column left, Column right) {
return left.value().compareTo(right.value());
}
}

View File

@@ -2,6 +2,7 @@ package org.springframework.data.cassandra.mapping;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.data.mapping.context.MappingContext;
import org.springframework.data.util.TypeInformation;
import com.datastax.driver.core.TableMetadata;
@@ -26,4 +27,24 @@ public interface CassandraMappingContext extends
* @param table May not be null.
*/
boolean usesTable(TableMetadata table);
/**
* Returns the {@link CassandraPersistentEntity} for the given type. If it doesn't exist, this method throws
* {@link IllegalArgumentException}.
*
* @param type The Java type of the persistent entity.
* @return The {@link CassandraPersistentEntity} describing the persistent Java type.
* @throws IllegalArgumentException if the persistent entity is unknown
*/
public CassandraPersistentEntity<?> getRequiredPersistentEntity(Class<?> type);
/**
* Returns the {@link CassandraPersistentEntity} for the given type. If it doesn't exist, this method throws
* {@link IllegalArgumentException}.
*
* @param type The {@link TypeInformation} of the persistent entity.
* @return The {@link CassandraPersistentEntity} describing the persistent Java type.
* @throws IllegalArgumentException if the persistent entity is unknown
*/
public CassandraPersistentEntity<?> getRequiredPersistentEntity(TypeInformation<?> type);
}

View File

@@ -15,6 +15,9 @@
*/
package org.springframework.data.cassandra.mapping;
import java.util.List;
import org.springframework.context.ApplicationContextAware;
import org.springframework.data.mapping.PersistentEntity;
import org.springframework.data.mapping.model.MutablePersistentEntity;
@@ -24,7 +27,15 @@ import org.springframework.data.mapping.model.MutablePersistentEntity;
* @author Alex Shvid
* @author Matthew T. Adams
*/
public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T, CassandraPersistentProperty> {
public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T, CassandraPersistentProperty>,
ApplicationContextAware {
/**
* Returns whether this entity represents a composite primary key.
*/
boolean isCompositePrimaryKey();
List<CassandraPersistentProperty> getCompositePrimaryKeyProperties();
/**
* Returns the table name to which the entity shall be persisted.
@@ -37,4 +48,6 @@ public interface CassandraPersistentEntity<T> extends MutablePersistentEntity<T,
* @param tableName The table name; must contain a valid Cassandra table name.
*/
void setTableName(String tableName);
CassandraMappingContext getMappingContext();
}

View File

@@ -15,8 +15,11 @@
*/
package org.springframework.data.cassandra.mapping;
import java.util.List;
import org.springframework.cassandra.core.Ordering;
import org.springframework.data.mapping.PersistentProperty;
import org.springframework.data.util.TypeInformation;
import com.datastax.driver.core.DataType;
@@ -33,12 +36,6 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
*/
boolean isCompositePrimaryKey();
/**
* Returns the type of the composite primary key class of this entity, or null if this class does not use a composite
* primary key.
*/
Class<?> getCompositePrimaryKeyType();
/**
* Returns a {@link CassandraPersistentEntity} representing the composite primary key class of this entity, or null if
* this class does not use a composite primary key.
@@ -46,22 +43,42 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
CassandraPersistentEntity<?> getCompositePrimaryKeyEntity();
/**
* The name of the column to which a property is persisted.
* Returns a {@link TypeInformation} representing the type of the composite primary key class of this entity, or null
* if this class does not use a composite primary key.
*/
TypeInformation<?> getCompositePrimaryKeyTypeInformation();
/**
* Gets the list of composite primary key properties that this composite primary key field is a placeholder for.
*/
List<CassandraPersistentProperty> getCompositePrimaryKeyProperties();
/**
* The name of the single column to which the property is persisted. This is a convenience method when the caller
* knows that the property is mapped to a single column. Throws {@link IllegalStateException} if this property is
* mapped to multiple columns.
*/
String getColumnName();
/**
* The ordering for the column. Valid only for clustered columns.
* The names of the columns to which the property is persisted if this is a composite primary key property. Never
* returns null.
*/
List<String> getColumnNames();
/**
* The ordering (ascending or descending) for the column. Valid only for primary key columns; returns null for
* non-primary key columns.
*/
Ordering getPrimaryKeyOrdering();
/**
* The column's data type.
* The column's data type. Not valid for a composite primary key, in which case this method returns null.
*/
DataType getDataType();
/**
* Whether the property has secondary index on this column.
* Whether the property has a secondary index on this column.
*/
boolean isIndexed();

View File

@@ -0,0 +1,87 @@
package org.springframework.data.cassandra.mapping;
import java.lang.reflect.Field;
import java.util.Comparator;
/**
* {@link Comparator} implementation that orders {@link CassandraPersistentProperty} instances.
* <p/>
* Composite primary key properties and primary key properties sort before non-primary key properties.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public enum CassandraPersistentPropertyComparator implements Comparator<CassandraPersistentProperty> {
/**
* The sole instance of this class.
*/
IT;
@Override
public int compare(CassandraPersistentProperty left, CassandraPersistentProperty right) {
if (left != null && right == null) {
return -1;
}
if (left == null && right != null) {
return 1;
}
if (left == null && right == null) {
return 0;
}
if (left.equals(right)) {
return 0;
}
boolean leftIsCompositePrimaryKey = left.isCompositePrimaryKey();
boolean rightIsCompositePrimaryKey = right.isCompositePrimaryKey();
if (leftIsCompositePrimaryKey && rightIsCompositePrimaryKey) {
return 0;
}
boolean leftIsPrimaryKey = left.isPrimaryKeyColumn();
boolean rightIsPrimaryKey = right.isPrimaryKeyColumn();
Field leftField = left.getField();
Field rightField = right.getField();
if (leftIsPrimaryKey && rightIsPrimaryKey) {
return CassandraPrimaryKeyColumnAnnotationComparator.IT.compare(leftField.getAnnotation(PrimaryKeyColumn.class),
rightField.getAnnotation(PrimaryKeyColumn.class));
}
boolean leftIsKey = leftIsCompositePrimaryKey || leftIsPrimaryKey;
boolean rightIsKey = rightIsCompositePrimaryKey || rightIsPrimaryKey;
if (leftIsKey && !rightIsKey) {
return 1;
}
if (!leftIsKey && rightIsKey) {
return -1;
}
// else, neither property is a composite primary key nor a primary key; compare @Column annotations
Column leftColumn = leftField.getAnnotation(Column.class);
Column rightColumn = rightField.getAnnotation(Column.class);
if (leftColumn == null && rightColumn == null) {
return leftField.getName().compareTo(rightField.getName());
}
if (leftColumn != null && rightColumn != null) {
return CassandraColumnAnnotationComparator.IT.compare(leftColumn, rightColumn);
}
if (leftColumn != null && rightColumn == null) {
return leftColumn.value().compareTo(rightField.getName());
}
// else leftColumn == null && rightColumn != null)
return leftField.getName().compareTo(rightColumn.value());
}
}

View File

@@ -19,7 +19,7 @@ import org.springframework.cassandra.core.PrimaryKeyType;
*
* @author Matthew T. Adams
*/
public enum DefaultCassandraPrimaryKeyColumnComparator implements Comparator<PrimaryKeyColumn> {
public enum CassandraPrimaryKeyColumnAnnotationComparator implements Comparator<PrimaryKeyColumn> {
/**
* The sole instance of this class.
@@ -27,23 +27,23 @@ public enum DefaultCassandraPrimaryKeyColumnComparator implements Comparator<Pri
IT;
@Override
public int compare(PrimaryKeyColumn o1, PrimaryKeyColumn o2) {
public int compare(PrimaryKeyColumn left, PrimaryKeyColumn right) {
int comparison = o1.type().compareTo(o2.type());
int comparison = left.type().compareTo(right.type());
if (comparison != 0) {
return comparison;
}
comparison = new Integer(o1.ordinal()).compareTo(o2.ordinal());
comparison = new Integer(left.ordinal()).compareTo(right.ordinal());
if (comparison != 0) {
return comparison;
}
comparison = o1.name().compareTo(o2.name());
comparison = left.name().compareTo(right.name());
if (comparison != 0) {
return comparison;
}
return o1.ordering().compareTo(o2.ordering());
return left.ordering().compareTo(right.ordering());
}
}

View File

@@ -15,6 +15,8 @@
*/
package org.springframework.data.cassandra.mapping;
import static org.springframework.cassandra.core.keyspace.CreateTableSpecification.createTable;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.util.HashMap;
@@ -73,7 +75,7 @@ public class DefaultCassandraMappingContext extends
@Override
protected <T> CassandraPersistentEntity<T> createPersistentEntity(TypeInformation<T> typeInformation) {
BasicCassandraPersistentEntity<T> entity = new BasicCassandraPersistentEntity<T>(typeInformation);
CassandraPersistentEntity<T> entity = new CachingCassandraPersistentEntity<T>(typeInformation, this);
if (context != null) {
entity.setApplicationContext(context);
@@ -104,9 +106,7 @@ public class DefaultCassandraMappingContext extends
Assert.notNull(entity);
final CreateTableSpecification spec = new CreateTableSpecification();
spec.name(entity.getTableName());
final CreateTableSpecification spec = createTable().name(entity.getTableName());
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@@ -124,7 +124,7 @@ public class DefaultCassandraMappingContext extends
if (pkProp.isPartitionKeyColumn()) {
spec.partitionKeyColumn(pkProp.getColumnName(), pkProp.getDataType());
} else {
} else { // it's a cluster column
spec.clusteredKeyColumn(pkProp.getColumnName(), pkProp.getDataType(), pkProp.getPrimaryKeyOrdering());
}
}
@@ -148,4 +148,29 @@ public class DefaultCassandraMappingContext extends
return spec;
}
@Override
public CassandraPersistentEntity<?> getRequiredPersistentEntity(Class<?> type) {
CassandraPersistentEntity<?> entity = getPersistentEntity(type);
if (entity == null) {
throw new IllegalArgumentException(String.format("no persistence metadata found for type [%s]", type.getName()));
}
return entity;
}
@Override
public CassandraPersistentEntity<?> getRequiredPersistentEntity(TypeInformation<?> type) {
CassandraPersistentEntity<?> entity = getPersistentEntity(type);
if (entity == null) {
throw new IllegalArgumentException(String.format("no persistence metadata found for type [%s]",
type.getActualType()));
}
return entity;
}
}

View File

@@ -1,22 +0,0 @@
package org.springframework.data.cassandra.mapping;
import java.util.Comparator;
/**
* {@link Comparator} implementation that uses the {@link CassandraPersistentProperty}'s column name for ordering.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public enum DefaultCassandraPersistentPropertyColumnComparator implements Comparator<CassandraPersistentProperty> {
/**
* The sole instance of this class.
*/
IT;
@Override
public int compare(CassandraPersistentProperty o1, CassandraPersistentProperty o2) {
return o1.getColumnName().compareTo(o2.getColumnName());
}
}

View File

@@ -1,4 +1,7 @@
package org.springframework.data.cassandra.config;
package org.springframework.data.cassandra.mapping;
import java.util.HashMap;
import java.util.Map;
/**
* Mapping information for an individual entity class.
@@ -7,9 +10,21 @@ package org.springframework.data.cassandra.config;
*/
public class EntityMapping {
/**
* The name of the entity's class.
*/
protected String entityClassName;
/**
* The name of the table to which the entity is mapped.
*/
protected String tableName;
/**
* The {@link PropertyMapping}s for each persistent property, keyed on property name.
*/
protected Map<String, PropertyMapping> propertyMappings = new HashMap<String, PropertyMapping>();
public EntityMapping(String entityClassName, String tableName) {
setEntityClassName(entityClassName);
setTableName(tableName);

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.config;
package org.springframework.data.cassandra.mapping;
import java.util.Collections;
import java.util.HashSet;

View File

@@ -21,6 +21,8 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.data.annotation.Persistent;
/**
* Annotates a type that represents the identity type of another class whose instances are stored in a table.
* <p/>
@@ -33,5 +35,6 @@ import java.lang.annotation.Target;
@Inherited
@Retention(RetentionPolicy.RUNTIME)
@Target({ ElementType.TYPE })
@Persistent
public @interface PrimaryKeyClass {
}

View File

@@ -0,0 +1,38 @@
package org.springframework.data.cassandra.mapping;
import org.springframework.util.Assert;
/**
* Mapping between a persistent entity's property and its column.
*
* @author Matthew T. Adams
*/
public class PropertyMapping {
protected String propertyName;
protected String columnName;
public PropertyMapping(String propertyName, String columnName) {
setPropertyName(propertyName);
setColumnName(columnName);
}
public String getPropertyName() {
return propertyName;
}
protected void setPropertyName(String propertyName) {
Assert.notNull(propertyName);
this.propertyName = propertyName;
}
public String getColumnName() {
return columnName;
}
protected void setColumnName(String columnName) {
Assert.notNull(columnName);
this.columnName = columnName;
}
}

View File

@@ -16,7 +16,6 @@
package org.springframework.data.cassandra.repository;
import java.io.Serializable;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
@@ -24,9 +23,7 @@ import org.springframework.data.repository.CrudRepository;
* Cassandra-specific extension of the {@link CrudRepository} interface.
*
* @author Alex Shvid
* @author Matthew T. Adams
*/
public interface CassandraRepository<T, ID extends Serializable> extends CrudRepository<T, ID> {
List<T> findByPartitionKey(ID id);
}

View File

@@ -33,12 +33,4 @@ public interface CassandraEntityInformation<T, ID extends Serializable> extends
* @return
*/
String getTableName();
/**
* Returns the column that the id will be persisted to.
*
* @return
*/
String getIdColumn();
}

View File

@@ -22,6 +22,7 @@ import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
import org.springframework.data.mapping.model.BeanWrapper;
import org.springframework.data.repository.core.support.AbstractEntityInformation;
import org.springframework.util.Assert;
/**
* {@link CassandraEntityInformation} implementation using a {@link CassandraPersistentEntity} instance to lookup the
@@ -59,49 +60,28 @@ public class MappingCassandraEntityInformation<T, ID extends Serializable> exten
this.customTableName = customTableName;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getId(java.lang.Object)
*/
@SuppressWarnings("unchecked")
@Override
public ID getId(T entity) {
CassandraPersistentProperty idProperty = entityMetadata.getIdProperty();
Assert.notNull(entity);
CassandraPersistentProperty idProperty = entityMetadata.getIdProperty();
if (idProperty == null) {
return null;
}
try {
return (ID) BeanWrapper.create(entity, null).getProperty(idProperty);
} catch (Exception e) {
throw new RuntimeException(e);
}
return (ID) BeanWrapper.create(entity, null).getProperty(idProperty);
}
/* (non-Javadoc)
* @see org.springframework.data.repository.support.EntityInformation#getIdType()
*/
@SuppressWarnings("unchecked")
@Override
public Class<ID> getIdType() {
return (Class<ID>) entityMetadata.getIdProperty().getType();
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.CassandraEntityInformation#getTableName()
*/
@Override
public String getTableName() {
return customTableName == null ? entityMetadata.getTableName() : customTableName;
}
/* (non-Javadoc)
* @see org.springframework.data.mongodb.repository.CassandraEntityInformation#getIdColumn()
*/
public String getIdColumn() {
return entityMetadata.getIdProperty().getName();
}
}

View File

@@ -16,33 +16,27 @@
package org.springframework.data.cassandra.repository.support;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.cassandra.core.CqlOperations;
import org.springframework.cassandra.core.util.CollectionUtils;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.core.CassandraTemplate;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
import org.springframework.util.Assert;
import com.datastax.driver.core.querybuilder.Clause;
import com.datastax.driver.core.querybuilder.Delete;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
/**
* Repository base implementation for Cassandra.
*
* @author Alex Shvid
*
* @author Matthew T. Adams
*/
public class SimpleCassandraRepository<T, ID extends Serializable> implements CassandraRepository<T, ID> {
private final CassandraTemplate cassandraTemplate;
private final CassandraEntityInformation<T, ID> entityInformation;
protected CassandraOperations template;
protected CassandraEntityInformation<T, ID> entityInformation;
/**
* Creates a new {@link SimpleCassandraRepository} for the given {@link CassandraEntityInformation} and
@@ -51,201 +45,71 @@ public class SimpleCassandraRepository<T, ID extends Serializable> implements Ca
* @param metadata must not be {@literal null}.
* @param template must not be {@literal null}.
*/
public SimpleCassandraRepository(CassandraEntityInformation<T, ID> metadata,
CassandraTemplate cassandraTemplate) {
public SimpleCassandraRepository(CassandraEntityInformation<T, ID> metadata, CassandraTemplate template) {
Assert.notNull(cassandraTemplate);
Assert.notNull(template);
Assert.notNull(metadata);
this.entityInformation = metadata;
this.cassandraTemplate = cassandraTemplate;
this.template = template;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Object)
*/
public <S extends T> S save(S entity) {
Assert.notNull(entity, "Entity must not be null!");
cassandraTemplate.insert(entity, entityInformation.getTableName());
return entity;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#save(java.lang.Iterable)
*/
public <S extends T> List<S> save(Iterable<S> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
List<S> result = new ArrayList<S>();
for (S entity : entities) {
save(entity);
result.add(entity);
}
return result;
}
private Clause getIdClause(ID id) {
Clause clause = QueryBuilder.eq(entityInformation.getIdColumn(), id);
return clause;
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findOne(java.io.Serializable)
*/
public T findOne(ID id) {
Assert.notNull(id, "The given id must not be null!");
Select select = QueryBuilder.select().all().from(entityInformation.getTableName());
select.where(getIdClause(id));
return cassandraTemplate.selectOne(select, entityInformation.getJavaType());
}
/*
* (non-Javadoc)
* @see org.springframework.data.cassandra.repository.CassandraRepository#findByPartitionKey(java.io.Serializable)
*/
@Override
public List<T> findByPartitionKey(ID id) {
Assert.notNull(id, "The given id must not be null!");
Select select = QueryBuilder.select().all().from(entityInformation.getTableName());
select.where(getIdClause(id));
return cassandraTemplate.select(select, entityInformation.getJavaType());
public <S extends T> S save(S entity) {
return template.insert(entity);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#exists(java.io.Serializable)
*/
@Override
public <S extends T> List<S> save(Iterable<S> entities) {
return template.insert(CollectionUtils.toList(entities));
}
@Override
public T findOne(ID id) {
return template.selectOneById(entityInformation.getJavaType(), id);
}
@Override
public boolean exists(ID id) {
Assert.notNull(id, "The given id must not be null!");
Select select = QueryBuilder.select().countAll().from(entityInformation.getTableName());
select.where(getIdClause(id));
Long num = cassandraTemplate.count(select);
return num != null && num.longValue() > 0;
return template.exists(entityInformation.getJavaType(), id);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#count()
*/
@Override
public long count() {
return cassandraTemplate.count(entityInformation.getTableName());
return template.count(entityInformation.getTableName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#delete(java.io.Serializable)
*/
@Override
public void delete(ID id) {
Assert.notNull(id, "The given id must not be null!");
Delete delete = QueryBuilder.delete().all().from(entityInformation.getTableName());
delete.where(getIdClause(id));
cassandraTemplate.execute(delete.getQueryString());
template.deleteById(entityInformation.getJavaType(), id);
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#delete(java.lang.Object)
*/
@Override
public void delete(T entity) {
Assert.notNull(entity, "The given entity must not be null!");
delete(entityInformation.getId(entity));
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#delete(java.lang.Iterable)
*/
@Override
public void delete(Iterable<? extends T> entities) {
Assert.notNull(entities, "The given Iterable of entities not be null!");
for (T entity : entities) {
delete(entity);
}
template.delete(CollectionUtils.toList(entities));
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#deleteAll()
*/
@Override
public void deleteAll() {
cassandraTemplate.truncate(entityInformation.getTableName());
template.truncate(entityInformation.getTableName());
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findAll()
*/
@Override
public List<T> findAll() {
Select select = QueryBuilder.select().all().from(entityInformation.getTableName());
return findAll(select);
return template.selectAll(entityInformation.getJavaType());
}
/*
* (non-Javadoc)
* @see org.springframework.data.repository.CrudRepository#findAll(java.lang.Iterable)
*/
@Override
public Iterable<T> findAll(Iterable<ID> ids) {
List<ID> parameters = new ArrayList<ID>();
for (ID id : ids) {
parameters.add(id);
}
Clause clause = QueryBuilder.in(entityInformation.getIdColumn(), parameters.toArray());
Select select = QueryBuilder.select().all().from(entityInformation.getTableName());
select.where(clause);
return findAll(select);
return template.selectBySimpleIds(entityInformation.getJavaType(), ids);
}
private List<T> findAll(Select query) {
if (query == null) {
return Collections.emptyList();
}
return cassandraTemplate.select(query, entityInformation.getJavaType());
protected List<T> findAll(Select query) {
return template.select(query.getQueryString(), entityInformation.getJavaType());
}
/**
* Returns the underlying {@link CqlOperations} instance.
*
* @return
*/
protected CqlOperations getCassandraOperations() {
return this.cassandraTemplate;
}
/**
* Returns the underlying {@link CassandraOperations} instance.
*
* @return
*/
protected CassandraOperations getCassandraDataOperations() {
return this.cassandraTemplate;
}
/**
* @return the entityInformation
*/
protected CassandraEntityInformation<T, ID> getEntityInformation() {
return entityInformation;
}
}

View File

@@ -3,25 +3,14 @@ package org.springframework.data.cassandra.util;
import java.util.ArrayList;
import java.util.List;
import org.springframework.cassandra.core.CqlTemplate;
import org.springframework.cassandra.core.QueryOptions;
import org.springframework.data.cassandra.exception.EntityWriterException;
import org.springframework.cassandra.core.cql.CqlStringUtils;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.convert.EntityWriter;
import org.springframework.data.mapping.PropertyHandler;
import com.datastax.driver.core.ColumnMetadata;
import com.datastax.driver.core.DataType;
import com.datastax.driver.core.Query;
import com.datastax.driver.core.Statement;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.querybuilder.Batch;
import com.datastax.driver.core.querybuilder.Delete;
import com.datastax.driver.core.querybuilder.Delete.Where;
import com.datastax.driver.core.querybuilder.Insert;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Update;
/**
* Utilities to convert Cassandra Annotated objects to Queries and CQL.
@@ -33,39 +22,7 @@ import com.datastax.driver.core.querybuilder.Update;
public abstract class CqlUtils {
/**
* Create the List of CQL for the indexes required for Cassandra mapped Table.
*
* @param tableName
* @param entity
* @return The list of CQL statements to run with session.execute()
*/
public static List<String> createIndexes(final String tableName, final CassandraPersistentEntity<?> entity) {
final List<String> result = new ArrayList<String>();
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
@Override
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
if (prop.isIndexed()) {
final StringBuilder str = new StringBuilder();
str.append("CREATE INDEX ON ");
str.append(tableName);
str.append(" (");
str.append(prop.getColumnName());
str.append(");");
result.add(str.toString());
}
}
});
return result;
}
/**
* Alter the table to refelct the entity annotations
* Alter the table to reflect the entity annotations
*
* @param tableName
* @param entity
@@ -104,7 +61,7 @@ public abstract class CqlUtils {
str.append("TYPE ");
}
str.append(toCQL(columnDataType));
str.append(CqlStringUtils.toCql(columnDataType));
str.append(';');
result.add(str.toString());
@@ -114,243 +71,4 @@ public abstract class CqlUtils {
return result;
}
/**
* Generates a Query Object for an insert
*
* @param tableName
* @param objectToSave
* @param entity
* @param optionsByName
*
* @return The Query object to run with session.execute();
* @throws EntityWriterException
*/
public static Query toInsertQuery(String tableName, final Object objectToSave, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
final Insert q = QueryBuilder.insertInto(tableName);
/*
* Write properties
*/
entityWriter.write(objectToSave, q);
/*
* Add Query Options
*/
CqlTemplate.addQueryOptions(q, options);
/*
* Add TTL to Insert object
*/
if (options != null && options.getTtl() != null) {
q.using(QueryBuilder.ttl(options.getTtl()));
}
return q;
}
/**
* Generates a Query Object for an Update
*
* @param tableName
* @param objectToSave
* @param entity
* @param optionsByName
*
* @return The Query object to run with session.execute();
* @throws EntityWriterException
*/
public static Query toUpdateQuery(String tableName, final Object objectToSave, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
final Update q = QueryBuilder.update(tableName);
/*
* Write properties
*/
entityWriter.write(objectToSave, q);
/*
* Add Query Options
*/
CqlTemplate.addQueryOptions(q, options);
/*
* Add TTL to Insert object
*/
if (options != null && options.getTtl() != null) {
q.using(QueryBuilder.ttl(options.getTtl()));
}
return q;
}
/**
* Generates a Batch Object for multiple Updates
*
* @param tableName
* @param objectsToSave
* @param entity
* @param optionsByName
*
* @return The Query object to run with session.execute();
* @throws EntityWriterException
*/
public static <T> Batch toUpdateBatchQuery(final String tableName, final List<T> objectsToSave, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
/*
* Return variable is a Batch statement
*/
final Batch b = QueryBuilder.batch();
for (final T objectToSave : objectsToSave) {
b.add((Statement) toUpdateQuery(tableName, objectToSave, options, entityWriter));
}
/*
* Add Query Options
*/
CqlTemplate.addQueryOptions(b, options);
return b;
}
/**
* Generates a Batch Object for multiple inserts
*
* @param tableName
* @param objectsToSave
* @param entity
* @param optionsByName
*
* @return The Query object to run with session.execute();
* @throws EntityWriterException
*/
public static <T> Batch toInsertBatchQuery(final String tableName, final List<T> objectsToSave, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
/*
* Return variable is a Batch statement
*/
final Batch b = QueryBuilder.batch();
for (final T objectToSave : objectsToSave) {
b.add((Statement) toInsertQuery(tableName, objectToSave, options, entityWriter));
}
/*
* Add Query Options
*/
CqlTemplate.addQueryOptions(b, options);
return b;
}
/**
* Create a Delete Query Object from an annotated POJO
*
* @param tableName
* @param objectToRemove
* @param entity
* @param optionsByName
* @return
* @throws EntityWriterException
*/
public static Query toDeleteQuery(String tableName, final Object objectToRemove, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
final Delete.Selection ds = QueryBuilder.delete();
final Delete q = ds.from(tableName);
final Where w = q.where();
/*
* Write where condition to find by Id
*/
entityWriter.write(objectToRemove, w);
CqlTemplate.addQueryOptions(q, options);
return q;
}
/**
* @param dataType
* @return
*/
public static String toCQL(DataType dataType) {
if (dataType.getTypeArguments().isEmpty()) {
return dataType.getName().name();
} else {
StringBuilder str = new StringBuilder();
str.append(dataType.getName().name());
str.append('<');
for (DataType argDataType : dataType.getTypeArguments()) {
if (str.charAt(str.length() - 1) != '<') {
str.append(',');
}
str.append(argDataType.getName().name());
}
str.append('>');
return str.toString();
}
}
/**
* @param tableName
* @return
*/
public static String dropTable(String tableName) {
if (tableName == null) {
return null;
}
StringBuilder str = new StringBuilder();
str.append("DROP TABLE " + tableName + ";");
return str.toString();
}
/**
* Create a Batch Query object for multiple deletes.
*
* @param tableName
* @param entities
* @param entity
* @param optionsByName
*
* @return
* @throws EntityWriterException
*/
public static <T> Batch toDeleteBatchQuery(String tableName, List<T> entities, QueryOptions options,
EntityWriter<Object, Object> entityWriter) throws EntityWriterException {
/*
* Return variable is a Batch statement
*/
final Batch b = QueryBuilder.batch();
for (final T objectToSave : entities) {
b.add((Statement) toDeleteQuery(tableName, objectToSave, options, entityWriter));
}
CqlTemplate.addQueryOptions(b, options);
return b;
}
}

View File

@@ -1,14 +1,84 @@
package org.springframework.data.cassandra.test.integration;
import static org.springframework.cassandra.core.keyspace.DropTableSpecification.dropTable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.test.integration.AbstractEmbeddedCassandraIntegrationTest;
import org.springframework.core.io.ClassPathResource;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.test.integration.support.SpringDataBuildProperties;
import org.springframework.data.cassandra.test.integration.template.CassandraDataOperationsTest.Config;
import org.springframework.util.Assert;
import com.datastax.driver.core.TableMetadata;
public class AbstractSpringDataEmbeddedCassandraIntegrationTest extends AbstractEmbeddedCassandraIntegrationTest {
static {
// override necessary superclass statics
public static List<String> SCRIPT;
public static List<TableMetadata> TABLES;
static {
SpringDataBuildProperties props = new SpringDataBuildProperties();
CASSANDRA_NATIVE_PORT = props.getCassandraPort();
}
public Logger log = LoggerFactory.getLogger(getClass());
@Autowired
public CassandraOperations template;
/**
* Saves all table metadata, then drops & creates all tables.
*/
public void recreateAllTables() {
saveAllTableMetadata();
for (TableMetadata table : TABLES) {
template.execute(dropTable(table.getName()));
template.execute(table.asCQLQuery());
}
}
public void saveAllTableMetadata() {
saveAllTableMetadata(false);
}
/**
* Saves all table metadata statically.
*/
public void saveAllTableMetadata(boolean force) {
if (TABLES != null && !force) {
return;
}
TABLES = new ArrayList<TableMetadata>(template.getSession().getCluster().getMetadata()
.getKeyspace(Config.KEYSPACE_NAME).getTables());
}
public List<String> readScriptLines(String resourceName) {
return readScriptLines(resourceName);
}
/**
* Reads the lines from the script referenced by {@link #RESOURCE}.
*/
public List<String> readScriptLines(String resourceName, boolean force) throws IOException {
if (SCRIPT != null && !force) {
return SCRIPT;
}
Assert.hasText(resourceName);
return SCRIPT = FileUtils.readLines(new ClassPathResource(resourceName).getFile());
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;
import java.util.Set;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;
import java.util.Map;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.composites;
import java.util.Date;

View File

@@ -1,38 +1,21 @@
package org.springframework.data.cassandra.test.integration.config;
import java.io.IOException;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.test.integration.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.util.Assert;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration
public class CassandraNamespaceTests {
public class CassandraNamespaceTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Autowired
private ApplicationContext ctx;
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("spring-cassandra.yaml");
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
@Test
public void test() {
Assert.notNull(ctx);

View File

@@ -1,5 +1,6 @@
package org.springframework.data.cassandra.test.integration.config;
import org.springframework.cassandra.test.unit.support.Utils;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.cassandra.config.java.AbstractSpringDataCassandraConfiguration;
@@ -23,7 +24,7 @@ public class TestConfig extends AbstractSpringDataCassandraConfiguration {
public static final int PORT = PROPS.getCassandraPort();
public static final int RPC_PORT = PROPS.getCassandraRpcPort();
public static final String KEYSPACE_NAME = "test";
public static final String KEYSPACE_NAME = Utils.randomKeyspaceName();
@Override
protected String getKeyspaceName() {

View File

@@ -19,13 +19,8 @@ import static org.hamcrest.CoreMatchers.is;
import static org.junit.Assert.assertThat;
import static org.mockito.Mockito.when;
import java.io.IOException;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
@@ -33,6 +28,7 @@ import org.mockito.runners.MockitoJUnitRunner;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.cassandra.test.integration.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.util.ClassTypeInformation;
/**
@@ -41,17 +37,11 @@ import org.springframework.data.util.ClassTypeInformation;
* @author Alex Shvid
*/
@RunWith(MockitoJUnitRunner.class)
public class BasicCassandraPersistentEntityIntegrationTests {
public class BasicCassandraPersistentEntityIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Mock
ApplicationContext context;
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("spring-cassandra.yaml");
}
@Test
public void subclassInheritsAtDocumentAnnotation() {
@@ -84,11 +74,6 @@ public class BasicCassandraPersistentEntityIntegrationTests {
assertThat(entity.getTableName(), is(bean.tableName));
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
@Table("messages")
static class Message {

View File

@@ -0,0 +1,126 @@
/*
* Copyright (c) 2011 by the original author(s).
*
* 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.mapping;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.List;
import org.junit.Before;
import org.junit.Test;
import org.springframework.cassandra.core.PrimaryKeyType;
import org.springframework.cassandra.core.keyspace.ColumnSpecification;
import org.springframework.cassandra.core.keyspace.CreateTableSpecification;
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CachingCassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
import org.springframework.data.cassandra.mapping.Column;
import org.springframework.data.cassandra.mapping.DefaultCassandraMappingContext;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.PrimaryKeyClass;
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
import org.springframework.data.cassandra.mapping.Table;
import org.springframework.data.util.ClassTypeInformation;
import org.springframework.util.ReflectionUtils;
import com.datastax.driver.core.DataType;
/**
* Integration test for {@link BasicCassandraPersistentProperty} with a composite primary key class.
*
* @author Matthew T. Adams
*/
public class CassandraCompositePrimaryKeyIntegrationTests {
private static final CassandraSimpleTypeHolder SIMPLE_TYPE_HOLDER = new CassandraSimpleTypeHolder();
@PrimaryKeyClass
static class Key {
@PrimaryKeyColumn(ordinal = 0, type = PrimaryKeyType.PARTITIONED)
String z;
@PrimaryKeyColumn(ordinal = 1, type = PrimaryKeyType.CLUSTERED)
String a;
}
@Table
static class Thing {
@PrimaryKey
Key id;
Date time;
@Column("message")
String text;
}
CassandraMappingContext context;
CassandraPersistentEntity<?> thing;
CassandraPersistentEntity<?> key;
@Before
public void setup() {
context = new DefaultCassandraMappingContext();
thing = context.getPersistentEntity(ClassTypeInformation.from(Thing.class));
key = context.getPersistentEntity(ClassTypeInformation.from(Key.class));
}
@Test
public void validateMappingInfo() {
Field field = ReflectionUtils.findField(Thing.class, "id");
CassandraPersistentProperty property = new CachingCassandraPersistentProperty(field, null, thing,
SIMPLE_TYPE_HOLDER);
assertTrue(property.isIdProperty());
assertTrue(property.isCompositePrimaryKey());
List<String> expectedColumnNames = Arrays.asList(new String[] { "z", "a" });
assertTrue(expectedColumnNames.equals(property.getColumnNames()));
List<String> actualColumnNames = new ArrayList<String>();
List<CassandraPersistentProperty> properties = property.getCompositePrimaryKeyProperties();
for (CassandraPersistentProperty p : properties) {
actualColumnNames.addAll(p.getColumnNames());
}
assertTrue(expectedColumnNames.equals(actualColumnNames));
CreateTableSpecification spec = context.getCreateTableSpecificationFor(thing);
List<ColumnSpecification> partitionKeyColumns = spec.getPartitionKeyColumns();
assertEquals(1, partitionKeyColumns.size());
ColumnSpecification partitionKeyColumn = partitionKeyColumns.get(0);
assertEquals("z", partitionKeyColumn.getName());
assertEquals(PrimaryKeyType.PARTITIONED, partitionKeyColumn.getKeyType());
assertEquals(DataType.text(), partitionKeyColumn.getType());
List<ColumnSpecification> clusteredKeyColumns = spec.getClusteredKeyColumns();
assertEquals(1, clusteredKeyColumns.size());
ColumnSpecification clusteredKeyColumn = clusteredKeyColumns.get(0);
assertEquals("a", clusteredKeyColumn.getName());
assertEquals(PrimaryKeyType.CLUSTERED, clusteredKeyColumn.getKeyType());
assertEquals(DataType.text(), partitionKeyColumn.getType());
}
}

View File

@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.BasicCassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CachingCassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
import org.springframework.data.cassandra.mapping.CassandraSimpleTypeHolder;
@@ -76,6 +77,6 @@ public class CompoundPrimaryKeyIntegrationTests {
}
private CassandraPersistentProperty getPropertyFor(Field field) {
return new BasicCassandraPersistentProperty(field, null, entity, new CassandraSimpleTypeHolder());
return new CachingCassandraPersistentProperty(field, null, entity, new CassandraSimpleTypeHolder());
}
}

View File

@@ -68,7 +68,7 @@ public class UserRepositoryJavaConfigIntegrationTests extends AbstractSpringData
}
@Override
public String getMappingBasePackage() {
public String getEntityBasePackage() {
return User.class.getPackage().getName();
}
}

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.simpletons;
import org.springframework.data.cassandra.mapping.PrimaryKey;
import org.springframework.data.cassandra.mapping.Table;

View File

@@ -13,7 +13,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.table;
package org.springframework.data.cassandra.test.integration.simpletons;
import java.util.Date;

View File

@@ -0,0 +1,22 @@
package org.springframework.data.cassandra.test.integration.support;
import org.cassandraunit.dataset.commons.AbstractCommonsParserDataSet;
import org.cassandraunit.dataset.commons.ParsedKeyspace;
public class ManualDataSet extends AbstractCommonsParserDataSet {
private String keyspaceName;
private ParsedKeyspace pks;
public ManualDataSet(String keyspaceName) {
this.keyspaceName = keyspaceName;
pks = new ParsedKeyspace();
pks.setName(this.keyspaceName);
}
@Override
protected ParsedKeyspace getParsedKeyspace() {
return pks;
}
}

View File

@@ -1,102 +0,0 @@
/*
* Copyright 2011-2013 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.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.cassandra.test.integration.template;
import java.io.IOException;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.DataLoader;
import org.cassandraunit.dataset.yaml.ClassPathYamlDataSet;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.Mock;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.CqlOperations;
import org.springframework.context.ApplicationContext;
import org.springframework.data.cassandra.test.integration.config.TestConfig;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
/**
* @author David Webb
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class CassandraAdminTest {
@Autowired
private CqlOperations cassandraTemplate;
@Mock
ApplicationContext context;
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra("spring-cassandra.yaml");
/*
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:" + TestConfig.RPC_PORT);
dataLoader.load(new ClassPathYamlDataSet("cassandra-keyspace.yaml"));
}
@Before
public void setupKeyspace() {
/*
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", "localhost:" + TestConfig.RPC_PORT);
dataLoader.load(new ClassPathYamlDataSet("cassandra-keyspace.yaml"));
}
@Test
public void alterTableTest() {
// cassandraTemplate.alterTable(UserAlter.class);
}
@Test
public void dropTableTest() {
// cassandraTemplate.dropTable(User.class);
// cassandraTemplate.dropTable("comments");
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
@AfterClass
public static void stopCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
}
}

View File

@@ -15,22 +15,18 @@
*/
package org.springframework.data.cassandra.test.integration.template;
import static org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification.createKeyspace;
import static org.springframework.cassandra.core.keyspace.DropTableSpecification.dropTable;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.UUID;
import org.apache.cassandra.exceptions.ConfigurationException;
import org.apache.thrift.transport.TTransportException;
import org.cassandraunit.CassandraCQLUnit;
import org.cassandraunit.DataLoader;
import org.cassandraunit.dataset.cql.ClassPathCQLDataSet;
import org.cassandraunit.dataset.yaml.ClassPathYamlDataSet;
import org.cassandraunit.utils.EmbeddedCassandraServerHelper;
import org.junit.After;
import org.apache.commons.io.FileUtils;
import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Rule;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
@@ -39,14 +35,19 @@ import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cassandra.core.ConsistencyLevel;
import org.springframework.cassandra.core.QueryOptions;
import org.springframework.cassandra.core.RetryPolicy;
import org.springframework.cassandra.core.keyspace.CreateKeyspaceSpecification;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.io.ClassPathResource;
import org.springframework.core.io.Resource;
import org.springframework.data.cassandra.config.SchemaAction;
import org.springframework.data.cassandra.core.CassandraOperations;
import org.springframework.data.cassandra.test.integration.AbstractSpringDataEmbeddedCassandraIntegrationTest;
import org.springframework.data.cassandra.test.integration.config.TestConfig;
import org.springframework.data.cassandra.test.integration.support.SpringDataBuildProperties;
import org.springframework.data.cassandra.test.integration.table.Book;
import org.springframework.data.cassandra.test.integration.simpletons.Book;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.support.AnnotationConfigContextLoader;
import com.datastax.driver.core.TableMetadata;
import com.datastax.driver.core.querybuilder.QueryBuilder;
import com.datastax.driver.core.querybuilder.Select;
@@ -57,51 +58,43 @@ import com.datastax.driver.core.querybuilder.Select;
*
*/
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = { TestConfig.class }, loader = AnnotationConfigContextLoader.class)
public class CassandraDataOperationsTest {
@ContextConfiguration
public class CassandraDataOperationsTest extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
@Autowired
private CassandraOperations cassandraTemplate;
@Configuration
public static class Config extends TestConfig {
private static Logger log = LoggerFactory.getLogger(CassandraDataOperationsTest.class);
@Override
public SchemaAction getSchemaAction() {
return SchemaAction.RECREATE;
}
public static final SpringDataBuildProperties PROPS = new SpringDataBuildProperties();
private final static String CASSANDRA_CONFIG = "spring-cassandra.yaml";
private final static String KEYSPACE_NAME = "test";
private final static String CASSANDRA_HOST = "localhost";
private final static int CASSANDRA_NATIVE_PORT = PROPS.getCassandraPort();
private final static int CASSANDRA_THRIFT_PORT = PROPS.getCassandraRpcPort();
@Override
protected List<CreateKeyspaceSpecification> getKeyspaceCreations() {
return Arrays.asList(createKeyspace().name(getKeyspaceName()).withSimpleReplication());
}
@Rule
public CassandraCQLUnit cassandraCQLUnit = new CassandraCQLUnit(new ClassPathCQLDataSet("cql-dataload.cql",
KEYSPACE_NAME), CASSANDRA_CONFIG, CASSANDRA_HOST, CASSANDRA_NATIVE_PORT);
@Override
public String getEntityBasePackage() {
return Book.class.getPackage().getName();
}
}
@BeforeClass
public static void startCassandra() throws IOException, TTransportException, ConfigurationException,
InterruptedException {
EmbeddedCassandraServerHelper.startEmbeddedCassandra(CASSANDRA_CONFIG);
/*
* Load data file to creat the test keyspace before we init the template
*/
DataLoader dataLoader = new DataLoader("Test Cluster", CASSANDRA_HOST + ":" + CASSANDRA_THRIFT_PORT);
dataLoader.load(new ClassPathYamlDataSet("cassandra-keyspace.yaml"));
@Before
public void before() throws IOException {
recreateAllTables();
}
@Test
public void insertTest() {
/*
* Test Single Insert with entity
*/
Book b1 = new Book();
b1.setIsbn("123456-1");
b1.setTitle("Spring Data Cassandra Guide");
b1.setAuthor("Cassandra Guru");
b1.setPages(521);
cassandraTemplate.insert(b1);
template.insert(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
@@ -109,11 +102,8 @@ public class CassandraDataOperationsTest {
b2.setAuthor("Cassandra Guru");
b2.setPages(521);
cassandraTemplate.insert(b2, "book_alt");
template.insert(b2);
/*
* Test Single Insert with entity
*/
Book b3 = new Book();
b3.setIsbn("123456-3");
b3.setTitle("Spring Data Cassandra Guide");
@@ -124,34 +114,27 @@ public class CassandraDataOperationsTest {
options.setConsistencyLevel(ConsistencyLevel.ONE);
options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY);
cassandraTemplate.insert(b3, "book", options);
template.insert(b3, options);
/*
* Test Single Insert with entity
*/
Book b5 = new Book();
b5.setIsbn("123456-5");
b5.setTitle("Spring Data Cassandra Guide");
b5.setAuthor("Cassandra Guru");
b5.setPages(265);
cassandraTemplate.insert(b5, options);
template.insert(b5, options);
}
@Test
public void insertAsynchronouslyTest() {
/*
* Test Single Insert with entity
*/
Book b1 = new Book();
b1.setIsbn("123456-1");
b1.setTitle("Spring Data Cassandra Guide");
b1.setAuthor("Cassandra Guru");
b1.setPages(521);
cassandraTemplate.insertAsynchronously(b1);
template.insertAsynchronously(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
@@ -159,7 +142,7 @@ public class CassandraDataOperationsTest {
b2.setAuthor("Cassandra Guru");
b2.setPages(521);
cassandraTemplate.insertAsynchronously(b2, "book_alt");
template.insertAsynchronously(b2);
/*
* Test Single Insert with entity
@@ -174,7 +157,7 @@ public class CassandraDataOperationsTest {
options.setConsistencyLevel(ConsistencyLevel.ONE);
options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY);
cassandraTemplate.insertAsynchronously(b3, "book", options);
template.insertAsynchronously(b3, options);
/*
* Test Single Insert with entity
@@ -194,7 +177,7 @@ public class CassandraDataOperationsTest {
b5.setAuthor("Cassandra Guru");
b5.setPages(265);
cassandraTemplate.insertAsynchronously(b5, options);
template.insertAsynchronously(b5, options);
}
@@ -209,19 +192,19 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book_alt");
template.insert(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book", options);
template.insert(books, options);
books = getBookList(20);
cassandraTemplate.insert(books, options);
template.insert(books, options);
}
@@ -236,19 +219,19 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insertAsynchronously(books);
template.insertAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insertAsynchronously(books, "book_alt");
template.insertAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insertAsynchronously(books, "book", options);
template.insertAsynchronously(books, options);
books = getBookList(20);
cassandraTemplate.insertAsynchronously(books, options);
template.insertAsynchronously(books, options);
}
@@ -290,7 +273,7 @@ public class CassandraDataOperationsTest {
b1.setAuthor("Cassandra Guru");
b1.setPages(521);
cassandraTemplate.update(b1);
template.update(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
@@ -298,7 +281,7 @@ public class CassandraDataOperationsTest {
b2.setAuthor("Cassandra Guru");
b2.setPages(521);
cassandraTemplate.update(b2, "book_alt");
template.update(b2);
/*
* Test Single Insert with entity
@@ -309,7 +292,7 @@ public class CassandraDataOperationsTest {
b3.setAuthor("Cassandra Guru");
b3.setPages(265);
cassandraTemplate.update(b3, "book", options);
template.update(b3, options);
/*
* Test Single Insert with entity
@@ -320,7 +303,7 @@ public class CassandraDataOperationsTest {
b5.setAuthor("Cassandra Guru");
b5.setPages(265);
cassandraTemplate.update(b5, options);
template.update(b5, options);
}
@@ -342,7 +325,7 @@ public class CassandraDataOperationsTest {
b1.setAuthor("Cassandra Guru");
b1.setPages(521);
cassandraTemplate.updateAsynchronously(b1);
template.updateAsynchronously(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
@@ -350,7 +333,7 @@ public class CassandraDataOperationsTest {
b2.setAuthor("Cassandra Guru");
b2.setPages(521);
cassandraTemplate.updateAsynchronously(b2, "book_alt");
template.updateAsynchronously(b2);
/*
* Test Single Insert with entity
@@ -361,7 +344,7 @@ public class CassandraDataOperationsTest {
b3.setAuthor("Cassandra Guru");
b3.setPages(265);
cassandraTemplate.updateAsynchronously(b3, "book", options);
template.updateAsynchronously(b3, options);
/*
* Test Single Insert with entity
@@ -372,7 +355,7 @@ public class CassandraDataOperationsTest {
b5.setAuthor("Cassandra Guru");
b5.setPages(265);
cassandraTemplate.updateAsynchronously(b5, options);
template.updateAsynchronously(b5, options);
}
@@ -387,35 +370,35 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
alterBooks(books);
cassandraTemplate.update(books);
template.update(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book_alt");
template.insert(books);
alterBooks(books);
cassandraTemplate.update(books, "book_alt");
template.update(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book", options);
template.insert(books, options);
alterBooks(books);
cassandraTemplate.update(books, "book", options);
template.update(books, options);
books = getBookList(20);
cassandraTemplate.insert(books, options);
template.insert(books, options);
alterBooks(books);
cassandraTemplate.update(books, options);
template.update(books, options);
}
@@ -430,35 +413,35 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
alterBooks(books);
cassandraTemplate.updateAsynchronously(books);
template.updateAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book_alt");
template.insert(books);
alterBooks(books);
cassandraTemplate.updateAsynchronously(books, "book_alt");
template.updateAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book", options);
template.insert(books, options);
alterBooks(books);
cassandraTemplate.updateAsynchronously(books, "book", options);
template.updateAsynchronously(books, options);
books = getBookList(20);
cassandraTemplate.insert(books, options);
template.insert(books, options);
alterBooks(books);
cassandraTemplate.updateAsynchronously(books, options);
template.updateAsynchronously(books, options);
}
@@ -489,12 +472,12 @@ public class CassandraDataOperationsTest {
Book b1 = new Book();
b1.setIsbn("123456-1");
cassandraTemplate.delete(b1);
template.delete(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
cassandraTemplate.delete(b2, "book_alt");
template.delete(b2);
/*
* Test Single Insert with entity
@@ -502,7 +485,7 @@ public class CassandraDataOperationsTest {
Book b3 = new Book();
b3.setIsbn("123456-3");
cassandraTemplate.delete(b3, "book", options);
template.delete(b3, options);
/*
* Test Single Insert with entity
@@ -510,7 +493,7 @@ public class CassandraDataOperationsTest {
Book b5 = new Book();
b5.setIsbn("123456-5");
cassandraTemplate.delete(b5, options);
template.delete(b5, options);
}
@@ -529,12 +512,12 @@ public class CassandraDataOperationsTest {
Book b1 = new Book();
b1.setIsbn("123456-1");
cassandraTemplate.deleteAsynchronously(b1);
template.deleteAsynchronously(b1);
Book b2 = new Book();
b2.setIsbn("123456-2");
cassandraTemplate.deleteAsynchronously(b2, "book_alt");
template.deleteAsynchronously(b2);
/*
* Test Single Insert with entity
@@ -542,7 +525,7 @@ public class CassandraDataOperationsTest {
Book b3 = new Book();
b3.setIsbn("123456-3");
cassandraTemplate.deleteAsynchronously(b3, "book", options);
template.deleteAsynchronously(b3, options);
/*
* Test Single Insert with entity
@@ -550,7 +533,7 @@ public class CassandraDataOperationsTest {
Book b5 = new Book();
b5.setIsbn("123456-5");
cassandraTemplate.deleteAsynchronously(b5, options);
template.deleteAsynchronously(b5, options);
}
@@ -565,27 +548,27 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
cassandraTemplate.delete(books);
template.delete(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book_alt");
template.insert(books);
cassandraTemplate.delete(books, "book_alt");
template.delete(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book", options);
template.insert(books, options);
cassandraTemplate.delete(books, "book", options);
template.delete(books, options);
books = getBookList(20);
cassandraTemplate.insert(books, options);
template.insert(books, options);
cassandraTemplate.delete(books, options);
template.delete(books, options);
}
@@ -600,27 +583,27 @@ public class CassandraDataOperationsTest {
books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
cassandraTemplate.deleteAsynchronously(books);
template.deleteAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book_alt");
template.insert(books);
cassandraTemplate.deleteAsynchronously(books, "book_alt");
template.deleteAsynchronously(books);
books = getBookList(20);
cassandraTemplate.insert(books, "book", options);
template.insert(books, options);
cassandraTemplate.deleteAsynchronously(books, "book", options);
template.deleteAsynchronously(books, options);
books = getBookList(20);
cassandraTemplate.insert(books, options);
template.insert(books, options);
cassandraTemplate.deleteAsynchronously(books, options);
template.deleteAsynchronously(books, options);
}
@@ -636,12 +619,12 @@ public class CassandraDataOperationsTest {
b1.setAuthor("Cassandra Guru");
b1.setPages(521);
cassandraTemplate.insert(b1);
template.insert(b1);
Select select = QueryBuilder.select().all().from("book");
select.where(QueryBuilder.eq("isbn", "123456-1"));
Book b = cassandraTemplate.selectOne(select, Book.class);
Book b = template.selectOne(select.getQueryString(), Book.class);
log.info("SingleSelect Book Title -> " + b.getTitle());
log.info("SingleSelect Book Author -> " + b.getAuthor());
@@ -656,11 +639,11 @@ public class CassandraDataOperationsTest {
List<Book> books = getBookList(20);
cassandraTemplate.insert(books);
template.insert(books);
Select select = QueryBuilder.select().all().from("book");
List<Book> b = cassandraTemplate.select(select, Book.class);
List<Book> b = template.select(select.getQueryString(), Book.class);
log.info("Book Count -> " + b.size());
@@ -671,23 +654,11 @@ public class CassandraDataOperationsTest {
@Test
public void selectCountTest() {
List<Book> books = getBookList(20);
int count = 20;
List<Book> books = getBookList(count);
cassandraTemplate.insert(books);
Select select = QueryBuilder.select().countAll().from("book");
Long count = cassandraTemplate.count(select);
log.info("Book Count -> " + count);
Assert.assertEquals(count, new Long(20));
}
@After
public void clearCassandra() {
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
template.insert(books);
Assert.assertEquals(count, template.count(Book.class));
}
}

View File

@@ -1,3 +1,3 @@
name: test
name: ks9487fb2da1a541e39a05e5545d64411a
replicationFactor: 1
strategy: org.apache.cassandra.locator.SimpleStrategy