Merge branch 'master' of local repository into DATACASS-89
This commit is contained in:
@@ -234,10 +234,6 @@ public class CassandraCqlClusterFactoryBean implements FactoryBean<Cluster>, Ini
|
||||
(CreateKeyspaceSpecification) spec).toCql() : new DropKeyspaceCqlGenerator(
|
||||
(DropKeyspaceSpecification) spec).toCql();
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("executing CQL [{}]", cql);
|
||||
}
|
||||
|
||||
template.execute(cql);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@ import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
import org.springframework.cassandra.core.cql.generator.AlterKeyspaceCqlGenerator;
|
||||
import org.springframework.cassandra.core.cql.generator.AlterTableCqlGenerator;
|
||||
@@ -89,6 +91,8 @@ import static org.springframework.cassandra.core.cql.CqlIdentifier.cqlId;
|
||||
*/
|
||||
public class CqlTemplate extends CassandraAccessor implements CqlOperations {
|
||||
|
||||
protected static final Logger log = LoggerFactory.getLogger(CqlTemplate.class);
|
||||
|
||||
/**
|
||||
* Add common {@link Query} options for all types of queries.
|
||||
*
|
||||
@@ -455,6 +459,11 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
|
||||
|
||||
@Override
|
||||
public ResultSet doInSession(Session s) throws DataAccessException {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("executing [{}]", q.toString());
|
||||
}
|
||||
|
||||
return s.execute(q);
|
||||
}
|
||||
});
|
||||
@@ -466,6 +475,10 @@ public class CqlTemplate extends CassandraAccessor implements CqlOperations {
|
||||
|
||||
@Override
|
||||
public ResultSetFuture doInSession(Session s) throws DataAccessException {
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("asynchronously executing [{}]", q.toString());
|
||||
}
|
||||
return s.executeAsync(q);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -0,0 +1,93 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
/**
|
||||
* Convenient converter that can be used to convert a single-row-single-column, single-row-multi-column, or multi-row
|
||||
* {@link ResultSet} into the a value of a given type. The majority of the expected usage is to convert a
|
||||
* single-row-single-column result set into the target type.
|
||||
* <p/>
|
||||
* The algorithm is:
|
||||
* <ul>
|
||||
* <li>if there is one row with one column, convert that value to this converter's type if possible or throw,</li>
|
||||
* <li>else if there is one row with multiple columns, convert the columns into this converter's type if possible or
|
||||
* throw,</li>
|
||||
* <li>else convert the rows into this converter's type (since there are multiple rows) or throw.</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* If the converter throws due to the inability to convert a given {@link ResultSet}, it will throw an
|
||||
* {@link IllegalArgumentException}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractResultSetConverter<T> implements Converter<ResultSet, T> {
|
||||
|
||||
/**
|
||||
* Converts the given value to this converter's type or throws {@link IllegalArgumentException}.
|
||||
*/
|
||||
protected abstract T doConvertSingleValue(Object object);
|
||||
|
||||
protected abstract Class<?> getType();
|
||||
|
||||
protected ResultSetToListConverter converter = new ResultSetToListConverter();
|
||||
|
||||
protected T getNullResultSetValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
protected T getExhaustedResultSetValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T convert(ResultSet source) {
|
||||
|
||||
if (source == null) {
|
||||
return getNullResultSetValue();
|
||||
}
|
||||
|
||||
if (source.isExhausted()) {
|
||||
return getExhaustedResultSetValue();
|
||||
}
|
||||
|
||||
List<Map<String, Object>> list = converter.convert(source);
|
||||
|
||||
if (list.size() == 1) {
|
||||
|
||||
Map<String, Object> map = list.get(0);
|
||||
return map.size() == 1 ? doConvertSingleValue(map.get(map.keySet().iterator().next())) : doConvertSingleRow(map);
|
||||
}
|
||||
|
||||
return doConvertResultSet(list);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given result set (as a {@link List}<{@link Map}<String,Object>>) to this converter's type
|
||||
* or throws {@link IllegalArgumentException}. This default implementation simply throws.
|
||||
*/
|
||||
protected T doConvertResultSet(List<Map<String, Object>> resultSet) {
|
||||
doThrow("result set");
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given row (as a {@link Map}<String,Object>) to this converter's type or throws
|
||||
* {@link IllegalArgumentException}. This default implementation simply throws.
|
||||
*/
|
||||
protected T doConvertSingleRow(Map<String, Object> row) {
|
||||
doThrow("row");
|
||||
return null;
|
||||
}
|
||||
|
||||
protected void doThrow(String string) {
|
||||
throw new IllegalArgumentException(String.format("can't convert %s to desired type [%s]", string, getType()
|
||||
.getName()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
|
||||
/**
|
||||
* Thin wrapper that allows subclasses to delegate conversion of the given value to a {@link DefaultConversionService}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractResultSetToBasicFixedTypeConverter<T> extends AbstractResultSetConverter<T> {
|
||||
|
||||
protected final static ConversionService CONVERTER = new DefaultConversionService();
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
public class ResultSetToArrayConverter implements Converter<ResultSet, Object[]> {
|
||||
|
||||
protected Converter<Row, Object[]> rowConverter;
|
||||
|
||||
public ResultSetToArrayConverter(Converter<Row, Object[]> rowConverter) {
|
||||
setRowConverter(rowConverter);
|
||||
}
|
||||
|
||||
public Converter<Row, Object[]> getRowConverter() {
|
||||
return rowConverter;
|
||||
}
|
||||
|
||||
public void setRowConverter(Converter<Row, Object[]> rowConverter) {
|
||||
|
||||
Assert.notNull(rowConverter);
|
||||
this.rowConverter = rowConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object[] convert(ResultSet resultSet) {
|
||||
|
||||
if (resultSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Object[]> list = new ArrayList<Object[]>();
|
||||
Iterator<Row> i = resultSet.iterator();
|
||||
while (i.hasNext()) {
|
||||
list.add(rowConverter.convert(i.next()));
|
||||
}
|
||||
|
||||
return list.toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
public class ResultSetToBigDecimalConverter extends AbstractResultSetToBasicFixedTypeConverter<BigDecimal> {
|
||||
|
||||
@Override
|
||||
protected BigDecimal doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, BigDecimal.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return BigDecimal.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class ResultSetToBigIntegerConverter extends AbstractResultSetToBasicFixedTypeConverter<BigInteger> {
|
||||
|
||||
@Override
|
||||
protected BigInteger doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, BigInteger.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return BigInteger.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
public class ResultSetToBooleanConverter extends AbstractResultSetToBasicFixedTypeConverter<Boolean> {
|
||||
|
||||
@Override
|
||||
protected Boolean doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Boolean.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Boolean.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.nio.ByteBuffer;
|
||||
|
||||
public class ResultSetToByteBufferConverter extends AbstractResultSetConverter<ByteBuffer> {
|
||||
|
||||
@Override
|
||||
protected ByteBuffer doConvertSingleValue(Object object) {
|
||||
|
||||
if (!(object instanceof ByteBuffer)) {
|
||||
doThrow("value");
|
||||
}
|
||||
|
||||
return (ByteBuffer) object;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return ByteBuffer.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class ResultSetToDateConverter extends AbstractResultSetToBasicFixedTypeConverter<Date> {
|
||||
|
||||
@Override
|
||||
protected Date doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Date.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Date.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
public class ResultSetToDoubleConverter extends AbstractResultSetToBasicFixedTypeConverter<Double> {
|
||||
|
||||
@Override
|
||||
protected Double doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Double.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Double.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
public class ResultSetToFloatConverter extends AbstractResultSetToBasicFixedTypeConverter<Float> {
|
||||
|
||||
@Override
|
||||
protected Float doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Float.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Float.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.net.InetAddress;
|
||||
|
||||
public class ResultSetToInetAddressConverter extends AbstractResultSetToBasicFixedTypeConverter<InetAddress> {
|
||||
|
||||
@Override
|
||||
protected InetAddress doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, InetAddress.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return InetAddress.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
public class ResultSetToIntegerConverter extends AbstractResultSetToBasicFixedTypeConverter<Integer> {
|
||||
|
||||
@Override
|
||||
protected Integer doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Integer.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Integer.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
public class ResultSetToListConverter implements Converter<ResultSet, List<Map<String, Object>>> {
|
||||
|
||||
protected Converter<Row, Map<String, Object>> rowConverter = new RowToMapConverter();
|
||||
|
||||
public ResultSetToListConverter() {
|
||||
}
|
||||
|
||||
public ResultSetToListConverter(Converter<Row, Map<String, Object>> rowConverter) {
|
||||
setRowConverter(rowConverter);
|
||||
}
|
||||
|
||||
public Converter<Row, Map<String, Object>> getRowConverter() {
|
||||
return rowConverter;
|
||||
}
|
||||
|
||||
public void setRowConverter(Converter<Row, Map<String, Object>> rowConverter) {
|
||||
|
||||
Assert.notNull(rowConverter);
|
||||
this.rowConverter = rowConverter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Map<String, Object>> convert(ResultSet resultSet) {
|
||||
|
||||
if (resultSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
|
||||
Iterator<Row> i = resultSet.iterator();
|
||||
while (i.hasNext()) {
|
||||
list.add(rowConverter.convert(i.next()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public class ResultSetToListOfStringConverter extends AbstractResultSetConverter<List<String>> {
|
||||
|
||||
@Override
|
||||
protected List<String> doConvertSingleValue(Object object) {
|
||||
|
||||
List<String> list = new ArrayList<String>();
|
||||
|
||||
list.add(object == null ? null : object.toString());
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doConvertSingleRow(Map<String, Object> row) {
|
||||
|
||||
List<String> list = new ArrayList<String>(row.size());
|
||||
|
||||
for (Object value : row.values()) {
|
||||
list.add(value == null ? null : value.toString());
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected List<String> doConvertResultSet(List<Map<String, Object>> resultSet) {
|
||||
|
||||
List<String> list = new ArrayList<String>(resultSet.size());
|
||||
|
||||
for (Map<String, Object> row : resultSet) {
|
||||
list.add(StringUtils.arrayToCommaDelimitedString(doConvertSingleRow(row).toArray()));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return List.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
public class ResultSetToLongConverter extends AbstractResultSetToBasicFixedTypeConverter<Long> {
|
||||
|
||||
@Override
|
||||
protected Long doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, Long.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return Long.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,61 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class ResultSetToStringConverter extends AbstractResultSetConverter<String> {
|
||||
|
||||
@Override
|
||||
protected String doConvertSingleValue(Object object) {
|
||||
return object == null ? null : object.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doConvertSingleRow(Map<String, Object> row) {
|
||||
|
||||
StringBuilder s = new StringBuilder();
|
||||
|
||||
boolean firstEntry = true;
|
||||
|
||||
for (Map.Entry<String, Object> entry : row.entrySet()) {
|
||||
|
||||
if (firstEntry) {
|
||||
firstEntry = false;
|
||||
} else {
|
||||
s.append(", ");
|
||||
}
|
||||
|
||||
s.append("\"").append(entry.getKey().replaceAll("\"", "\\\"")).append("\"");
|
||||
s.append(" : ");
|
||||
s.append("\"").append(entry.getValue().toString().replaceAll("\"", "\\\"")).append("\"");
|
||||
}
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String doConvertResultSet(List<Map<String, Object>> resultSet) {
|
||||
|
||||
boolean firstElement = true;
|
||||
StringBuilder s = new StringBuilder("{ ");
|
||||
|
||||
for (Map<String, Object> map : resultSet) {
|
||||
|
||||
if (firstElement) {
|
||||
firstElement = false;
|
||||
} else {
|
||||
s.append(", ");
|
||||
}
|
||||
|
||||
s.append(doConvertSingleRow(map));
|
||||
}
|
||||
s.append(" }");
|
||||
|
||||
return s.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return String.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.UUID;
|
||||
|
||||
public class ResultSetToUuidConverter extends AbstractResultSetToBasicFixedTypeConverter<UUID> {
|
||||
|
||||
@Override
|
||||
protected UUID doConvertSingleValue(Object object) {
|
||||
return CONVERTER.convert(object, UUID.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> getType() {
|
||||
return UUID.class;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
public class RowToArrayConverter implements Converter<Row, Object[]> {
|
||||
|
||||
protected RowToListConverter delegate = new RowToListConverter();
|
||||
|
||||
@Override
|
||||
public Object[] convert(Row row) {
|
||||
|
||||
List<Object> list = delegate.convert(row);
|
||||
return list == null ? null : list.toArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.datastax.driver.core.ColumnDefinitions;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.ColumnDefinitions.Definition;
|
||||
|
||||
public class RowToListConverter implements Converter<Row, List<Object>> {
|
||||
|
||||
@Override
|
||||
public List<Object> convert(Row row) {
|
||||
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ColumnDefinitions cols = row.getColumnDefinitions();
|
||||
List<Object> list = new ArrayList<Object>(cols.size());
|
||||
|
||||
for (Definition def : cols.asList()) {
|
||||
String name = def.getName();
|
||||
list.add(row.isNull(name) ? null : def.getType().deserialize(row.getBytesUnsafe(name)));
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
package org.springframework.cassandra.core.converter;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
|
||||
import com.datastax.driver.core.ColumnDefinitions;
|
||||
import com.datastax.driver.core.ColumnDefinitions.Definition;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
public class RowToMapConverter implements Converter<Row, Map<String, Object>> {
|
||||
|
||||
@Override
|
||||
public Map<String, Object> convert(Row row) {
|
||||
|
||||
if (row == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ColumnDefinitions cols = row.getColumnDefinitions();
|
||||
Map<String, Object> map = new HashMap<String, Object>(cols.size());
|
||||
|
||||
for (Definition def : cols.asList()) {
|
||||
|
||||
String name = def.getName();
|
||||
map.put(name, row.isNull(name) ? null : def.getType().deserialize(row.getBytesUnsafe(name)));
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -15,8 +15,6 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
@@ -25,7 +23,6 @@ import org.springframework.data.mapping.model.PropertyValueProvider;
|
||||
import org.springframework.data.mapping.model.SpELExpressionEvaluator;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
@@ -37,9 +34,7 @@ import com.datastax.driver.core.Row;
|
||||
*/
|
||||
public class BasicCassandraRowValueProvider implements CassandraRowValueProvider {
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(BasicCassandraRowValueProvider.class);
|
||||
|
||||
private final Row source;
|
||||
private final ColumnReader reader;
|
||||
private final SpELExpressionEvaluator evaluator;
|
||||
|
||||
/**
|
||||
@@ -53,88 +48,24 @@ public class BasicCassandraRowValueProvider implements CassandraRowValueProvider
|
||||
Assert.notNull(source);
|
||||
Assert.notNull(evaluator);
|
||||
|
||||
this.source = source;
|
||||
this.reader = new ColumnReader(source);
|
||||
this.evaluator = evaluator;
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T getPropertyValue(CassandraPersistentProperty property) {
|
||||
public Object getPropertyValue(CassandraPersistentProperty property) {
|
||||
|
||||
String expression = property.getSpelExpression();
|
||||
if (expression != null) {
|
||||
return evaluator.evaluate(expression);
|
||||
}
|
||||
|
||||
String columnName = property.getColumnName().toCql();
|
||||
if (source.isNull(columnName)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType columnType = source.getColumnDefinitions().getType(columnName);
|
||||
|
||||
/*
|
||||
* Handle the types of collections that are available
|
||||
*/
|
||||
if (columnType.isCollection()) {
|
||||
|
||||
List<DataType> collectionTypes = columnType.getTypeArguments();
|
||||
if (collectionTypes.size() == 2) {
|
||||
return (T) source
|
||||
.getMap(columnName, collectionTypes.get(0).asJavaClass(), collectionTypes.get(1).asJavaClass());
|
||||
}
|
||||
|
||||
if (columnType.equals(DataType.list(collectionTypes.get(0)))) {
|
||||
return (T) source.getList(columnName, collectionTypes.get(0).asJavaClass());
|
||||
}
|
||||
|
||||
if (columnType.equals(DataType.set(collectionTypes.get(0)))) {
|
||||
return (T) source.getSet(columnName, collectionTypes.get(0).asJavaClass());
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unknown Collection type encountered. Valid collections are Set, List and Map.");
|
||||
}
|
||||
|
||||
if (columnType.equals(DataType.text()) || columnType.equals(DataType.ascii())
|
||||
|| columnType.equals(DataType.varchar())) {
|
||||
return (T) source.getString(columnName);
|
||||
}
|
||||
if (columnType.equals(DataType.cint()) || columnType.equals(DataType.varint())) {
|
||||
return (T) new Integer(source.getInt(columnName));
|
||||
}
|
||||
if (columnType.equals(DataType.cdouble())) {
|
||||
return (T) new Double(source.getDouble(columnName));
|
||||
}
|
||||
if (columnType.equals(DataType.bigint()) || columnType.equals(DataType.counter())) {
|
||||
return (T) new Long(source.getLong(columnName));
|
||||
}
|
||||
if (columnType.equals(DataType.cfloat())) {
|
||||
return (T) new Float(source.getFloat(columnName));
|
||||
}
|
||||
if (columnType.equals(DataType.decimal())) {
|
||||
return (T) source.getDecimal(columnName);
|
||||
}
|
||||
if (columnType.equals(DataType.cboolean())) {
|
||||
return (T) new Boolean(source.getBool(columnName));
|
||||
}
|
||||
if (columnType.equals(DataType.timestamp())) {
|
||||
return (T) source.getDate(columnName);
|
||||
}
|
||||
if (columnType.equals(DataType.blob())) {
|
||||
return (T) source.getBytes(columnName);
|
||||
}
|
||||
if (columnType.equals(DataType.inet())) {
|
||||
return (T) source.getInet(columnName);
|
||||
}
|
||||
if (columnType.equals(DataType.uuid()) || columnType.equals(DataType.timeuuid())) {
|
||||
return (T) source.getUUID(columnName);
|
||||
}
|
||||
|
||||
return (T) source.getBytes(columnName);
|
||||
return reader.get(property.getColumnName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Row getRow() {
|
||||
return source;
|
||||
return reader.getRow();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,142 @@
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
|
||||
import com.datastax.driver.core.ColumnDefinitions;
|
||||
import com.datastax.driver.core.DataType;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* Helpful class to read a column's value from a row, with possible type conversion.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public class ColumnReader {
|
||||
|
||||
protected Row row;
|
||||
protected ColumnDefinitions columns;
|
||||
|
||||
public ColumnReader(Row row) {
|
||||
this.row = row;
|
||||
this.columns = row.getColumnDefinitions();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row's column value.
|
||||
*/
|
||||
public Object get(CqlIdentifier name) {
|
||||
return get(name.toCql());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row's column value.
|
||||
*/
|
||||
public Object get(String name) {
|
||||
return get(columns.getIndexOf(name));
|
||||
}
|
||||
|
||||
public Object get(int i) {
|
||||
|
||||
if (row.isNull(i)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
DataType type = columns.getType(i);
|
||||
|
||||
if (type.isCollection()) {
|
||||
|
||||
List<DataType> collectionTypes = type.getTypeArguments();
|
||||
if (collectionTypes.size() == 2) {
|
||||
return row.getMap(i, collectionTypes.get(0).asJavaClass(), collectionTypes.get(1).asJavaClass());
|
||||
}
|
||||
|
||||
if (type.equals(DataType.list(collectionTypes.get(0)))) {
|
||||
return row.getList(i, collectionTypes.get(0).asJavaClass());
|
||||
}
|
||||
|
||||
if (type.equals(DataType.set(collectionTypes.get(0)))) {
|
||||
return row.getSet(i, collectionTypes.get(0).asJavaClass());
|
||||
}
|
||||
|
||||
throw new IllegalStateException("Unknown Collection type encountered. Valid collections are Set, List and Map.");
|
||||
}
|
||||
|
||||
if (type.equals(DataType.text()) || type.equals(DataType.ascii()) || type.equals(DataType.varchar())) {
|
||||
return row.getString(i);
|
||||
}
|
||||
if (type.equals(DataType.cint()) || type.equals(DataType.varint())) {
|
||||
return new Integer(row.getInt(i));
|
||||
}
|
||||
if (type.equals(DataType.cdouble())) {
|
||||
return new Double(row.getDouble(i));
|
||||
}
|
||||
if (type.equals(DataType.bigint()) || type.equals(DataType.counter())) {
|
||||
return new Long(row.getLong(i));
|
||||
}
|
||||
if (type.equals(DataType.cfloat())) {
|
||||
return new Float(row.getFloat(i));
|
||||
}
|
||||
if (type.equals(DataType.decimal())) {
|
||||
return row.getDecimal(i);
|
||||
}
|
||||
if (type.equals(DataType.cboolean())) {
|
||||
return new Boolean(row.getBool(i));
|
||||
}
|
||||
if (type.equals(DataType.timestamp())) {
|
||||
return row.getDate(i);
|
||||
}
|
||||
if (type.equals(DataType.blob())) {
|
||||
return row.getBytes(i);
|
||||
}
|
||||
if (type.equals(DataType.inet())) {
|
||||
return row.getInet(i);
|
||||
}
|
||||
if (type.equals(DataType.uuid()) || type.equals(DataType.timeuuid())) {
|
||||
return row.getUUID(i);
|
||||
}
|
||||
|
||||
return row.getBytesUnsafe(i);
|
||||
}
|
||||
|
||||
public Row getRow() {
|
||||
return row;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row's column value as an instance of the given type.
|
||||
*
|
||||
* @throws ClassCastException if the value cannot be converted to the requested type.
|
||||
*/
|
||||
public <T> T get(CqlIdentifier name, Class<T> requestedType) {
|
||||
return get(columns.getIndexOf(name.toCql()), requestedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row's column value as an instance of the given type.
|
||||
*
|
||||
* @throws ClassCastException if the value cannot be converted to the requested type.
|
||||
*/
|
||||
public <T> T get(String name, Class<T> requestedType) {
|
||||
return get(columns.getIndexOf(name), requestedType);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the row's column value as an instance of the given type.
|
||||
*
|
||||
* @throws ClassCastException if the value cannot be converted to the requested type.
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> T get(int i, Class<T> requestedType) {
|
||||
|
||||
Object o = get(i);
|
||||
|
||||
if (o == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T) o;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -15,7 +15,7 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.convert;
|
||||
|
||||
import static org.springframework.data.cassandra.repository.support.BasicMapId.id;
|
||||
import static org.springframework.data.cassandra.repository.support.BasicMapId.*;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
@@ -56,6 +56,7 @@ import com.datastax.driver.core.querybuilder.Update;
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
* @author Oliver Gierke
|
||||
*/
|
||||
public class MappingCassandraConverter extends AbstractCassandraConverter implements CassandraConverter,
|
||||
ApplicationContextAware, BeanClassLoaderAware {
|
||||
@@ -65,7 +66,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
protected final CassandraMappingContext mappingContext;
|
||||
protected ApplicationContext applicationContext;
|
||||
protected SpELContext spELContext;
|
||||
protected boolean useFieldAccessOnly = true;
|
||||
|
||||
protected ClassLoader beanClassLoader;
|
||||
|
||||
@@ -124,7 +124,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
EntityInstantiator instantiator = instantiators.getInstantiatorFor(entity);
|
||||
S instance = instantiator.createInstance(entity, parameterProvider);
|
||||
|
||||
BeanWrapper<CassandraPersistentEntity<S>, S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
BeanWrapper<S> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
|
||||
readPropertiesFromRow(entity, rowValueProvider, wrapper);
|
||||
|
||||
@@ -132,7 +132,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void readPropertiesFromRow(final CassandraPersistentEntity<?> entity,
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?, ?> wrapper) {
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?> wrapper) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@@ -145,7 +145,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void readPropertyFromRow(final CassandraPersistentEntity<?> entity, final CassandraPersistentProperty prop,
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?, ?> wrapper) {
|
||||
final BasicCassandraRowValueProvider row, final BeanWrapper<?> wrapper) {
|
||||
|
||||
if (entity.isConstructorArgument(prop)) { // skip 'cause prop was set in ctor
|
||||
return;
|
||||
@@ -161,14 +161,13 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
// wrap the key
|
||||
@SuppressWarnings("rawtypes")
|
||||
BeanWrapper keyWrapper = BeanWrapper.create(key, conversionService);
|
||||
BeanWrapper<Object> keyWrapper = BeanWrapper.create(key, conversionService);
|
||||
|
||||
// now recurse on using the key this time
|
||||
readPropertiesFromRow(prop.getCompositePrimaryKeyEntity(), row, keyWrapper);
|
||||
|
||||
// now that the key's properties have been populated, set the key property on the entity
|
||||
wrapper.setProperty(keyProperty, keyWrapper.getBean(), useFieldAccessOnly);
|
||||
wrapper.setProperty(keyProperty, keyWrapper.getBean());
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -177,7 +176,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
Object obj = row.getPropertyValue(prop);
|
||||
wrapper.setProperty(prop, obj, useFieldAccessOnly);
|
||||
wrapper.setProperty(prop, obj);
|
||||
}
|
||||
|
||||
protected Object instantiatePrimaryKey(CassandraPersistentEntity<?> entity, CassandraPersistentProperty keyProperty,
|
||||
@@ -189,14 +188,6 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
propertyProvider, null));
|
||||
}
|
||||
|
||||
public boolean getUseFieldAccessOnly() {
|
||||
return useFieldAccessOnly;
|
||||
}
|
||||
|
||||
public void setUseFieldAccessOnly(boolean useFieldAccessOnly) {
|
||||
this.useFieldAccessOnly = useFieldAccessOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <R> R read(Class<R> type, Object row) {
|
||||
if (row instanceof Row) {
|
||||
@@ -231,23 +222,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void writeInsertFromObject(final Object object, final Insert insert, CassandraPersistentEntity<?> entity) {
|
||||
writeInsertFromWrapper(BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService),
|
||||
insert, entity);
|
||||
writeInsertFromWrapper(BeanWrapper.create(object, conversionService), insert, entity);
|
||||
}
|
||||
|
||||
protected void writeInsertFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
|
||||
final Insert insert, CassandraPersistentEntity<?> entity) {
|
||||
protected void writeInsertFromWrapper(final BeanWrapper<Object> wrapper, final Insert insert,
|
||||
CassandraPersistentEntity<?> entity) {
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty prop) {
|
||||
|
||||
Object value = wrapper.getProperty(prop, prop.getType(), useFieldAccessOnly);
|
||||
Object value = wrapper.getProperty(prop, prop.getType());
|
||||
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
writeInsertFromWrapper(
|
||||
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(value, conversionService), insert,
|
||||
writeInsertFromWrapper(BeanWrapper.create(value, conversionService), insert,
|
||||
prop.getCompositePrimaryKeyEntity());
|
||||
return;
|
||||
}
|
||||
@@ -260,23 +249,21 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void writeUpdateFromObject(final Object object, final Update update, CassandraPersistentEntity<?> entity) {
|
||||
writeUpdateFromWrapper(BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService),
|
||||
update, entity);
|
||||
writeUpdateFromWrapper(BeanWrapper.create(object, conversionService), update, entity);
|
||||
}
|
||||
|
||||
protected void writeUpdateFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
|
||||
final Update update, final CassandraPersistentEntity<?> entity) {
|
||||
protected void writeUpdateFromWrapper(final BeanWrapper<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);
|
||||
Object value = wrapper.getProperty(prop, prop.getType());
|
||||
|
||||
if (prop.isCompositePrimaryKey()) {
|
||||
writeUpdateFromWrapper(
|
||||
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(value, conversionService), update,
|
||||
writeUpdateFromWrapper(BeanWrapper.create(value, conversionService), update,
|
||||
prop.getCompositePrimaryKeyEntity());
|
||||
return;
|
||||
}
|
||||
@@ -293,12 +280,11 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
}
|
||||
|
||||
protected void writeDeleteWhereFromObject(final Object object, final Where where, CassandraPersistentEntity<?> entity) {
|
||||
writeDeleteWhereFromWrapper(
|
||||
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(object, conversionService), where, entity);
|
||||
writeDeleteWhereFromWrapper(BeanWrapper.create(object, conversionService), where, entity);
|
||||
}
|
||||
|
||||
protected void writeDeleteWhereFromWrapper(final BeanWrapper<CassandraPersistentEntity<Object>, Object> wrapper,
|
||||
final Where where, CassandraPersistentEntity<?> entity) {
|
||||
protected void writeDeleteWhereFromWrapper(final BeanWrapper<Object> wrapper, final Where where,
|
||||
CassandraPersistentEntity<?> entity) {
|
||||
|
||||
Object id = getId(wrapper, entity);
|
||||
if (id == null) {
|
||||
@@ -319,8 +305,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
if (idProperty != null) {
|
||||
|
||||
if (idProperty.isCompositePrimaryKey()) {
|
||||
writeDeleteWhereFromWrapper(
|
||||
BeanWrapper.<CassandraPersistentEntity<Object>, Object> create(id, conversionService), where,
|
||||
writeDeleteWhereFromWrapper(BeanWrapper.create(id, conversionService), where,
|
||||
idProperty.getCompositePrimaryKeyEntity());
|
||||
return;
|
||||
}
|
||||
@@ -335,8 +320,8 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
|
||||
Assert.notNull(object);
|
||||
|
||||
final BeanWrapper<?, ?> wrapper = (object instanceof BeanWrapper) ? (BeanWrapper<?, ?>) object : BeanWrapper
|
||||
.create(object, conversionService);
|
||||
final BeanWrapper<?> wrapper = object instanceof BeanWrapper ? (BeanWrapper<?>) object : BeanWrapper.create(object,
|
||||
conversionService);
|
||||
object = wrapper == null ? object : wrapper.getBean();
|
||||
|
||||
if (!entity.getType().isAssignableFrom(object.getClass())) {
|
||||
@@ -351,7 +336,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
|
||||
CassandraPersistentProperty idProperty = entity.getIdProperty();
|
||||
if (idProperty != null) {
|
||||
return wrapper.getProperty(entity.getIdProperty(), idProperty.getType(), useFieldAccessOnly);
|
||||
return wrapper.getProperty(entity.getIdProperty(), idProperty.getType());
|
||||
}
|
||||
|
||||
// if the class doesn't have an id property, then it's using MapId
|
||||
@@ -361,7 +346,7 @@ public class MappingCassandraConverter extends AbstractCassandraConverter implem
|
||||
@Override
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
if (p.isPrimaryKeyColumn()) {
|
||||
id.with(p.getName(), (Serializable) wrapper.getProperty(p, p.getType(), useFieldAccessOnly));
|
||||
id.with(p.getName(), (Serializable) wrapper.getProperty(p, p.getType()));
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
@@ -62,6 +62,8 @@ public class CassandraAdminTemplate extends CassandraTemplate implements Cassand
|
||||
String cql = new CreateTableCqlGenerator(getCassandraMappingContext().getCreateTableSpecificationFor(entity))
|
||||
.toCql();
|
||||
|
||||
log.debug(cql);
|
||||
|
||||
s.execute(cql);
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -55,20 +55,18 @@ import com.datastax.driver.core.querybuilder.Update;
|
||||
* @author Alex Shvid
|
||||
* @author David Webb
|
||||
* @author Matthew T. Adams
|
||||
*
|
||||
* @author Oliver Gierke
|
||||
* @see CqlTemplate
|
||||
*/
|
||||
public class CassandraTemplate extends CqlTemplate implements CassandraOperations {
|
||||
|
||||
protected CassandraConverter cassandraConverter;
|
||||
protected CassandraMappingContext mappingContext;
|
||||
protected boolean useFieldAccessOnly = false;
|
||||
|
||||
/**
|
||||
* Default Constructor for wiring in the required components later
|
||||
*/
|
||||
public CassandraTemplate() {
|
||||
}
|
||||
public CassandraTemplate() {}
|
||||
|
||||
/**
|
||||
* Constructor if only session and converter are known at time of Template Creation
|
||||
@@ -98,19 +96,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
return mappingContext;
|
||||
}
|
||||
|
||||
public boolean getUseFieldAccessOnly() {
|
||||
return useFieldAccessOnly;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether only fields should be used when accessing a persistent entity's data.
|
||||
*
|
||||
* @param useFieldAccessOnly
|
||||
*/
|
||||
public void setUseFieldAccessOnly(boolean useFieldAccessOnly) {
|
||||
this.useFieldAccessOnly = useFieldAccessOnly;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
@@ -313,8 +298,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
|
||||
CassandraPersistentEntity<?> idEntity = idProperty.getCompositePrimaryKeyEntity();
|
||||
|
||||
final BeanWrapper<CassandraPersistentEntity<Object>, Object> idWrapper = BeanWrapper
|
||||
.<CassandraPersistentEntity<Object>, Object> create(id, cassandraConverter.getConversionService());
|
||||
final BeanWrapper<Object> idWrapper = BeanWrapper.create(id, cassandraConverter.getConversionService());
|
||||
|
||||
idEntity.doWithProperties(new PropertyHandler<CassandraPersistentProperty>() {
|
||||
|
||||
@@ -322,7 +306,7 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
public void doWithPersistentProperty(CassandraPersistentProperty p) {
|
||||
|
||||
clauseCallback.doWithClause(QueryBuilder.eq(p.getColumnName().toCql(),
|
||||
idWrapper.getProperty(p, p.getActualType(), useFieldAccessOnly)));
|
||||
idWrapper.getProperty(p, p.getActualType())));
|
||||
}
|
||||
});
|
||||
|
||||
@@ -595,7 +579,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
* @param objectToSave
|
||||
* @param entity
|
||||
* @param optionsByName
|
||||
*
|
||||
* @return The Query object to run with session.execute();
|
||||
*/
|
||||
public static Insert createInsertQuery(String tableName, Object objectToSave, QueryOptions options,
|
||||
@@ -623,7 +606,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
* @param objectToSave
|
||||
* @param entity
|
||||
* @param optionsByName
|
||||
*
|
||||
* @return The Query object to run with session.execute();
|
||||
*/
|
||||
public static Update toUpdateQuery(String tableName, Object objectToSave, QueryOptions options,
|
||||
@@ -651,7 +633,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
* @param objectsToSave
|
||||
* @param entity
|
||||
* @param optionsByName
|
||||
*
|
||||
* @return The Query object to run with session.execute();
|
||||
*/
|
||||
public static <T> Batch toUpdateBatchQuery(String tableName, List<T> objectsToSave, QueryOptions options,
|
||||
@@ -684,7 +665,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
* @param entities
|
||||
* @param entity
|
||||
* @param optionsByName
|
||||
*
|
||||
* @return The Query object to run with session.execute();
|
||||
*/
|
||||
public static <T> Batch createInsertBatchQuery(String tableName, List<T> entities, QueryOptions options,
|
||||
@@ -731,7 +711,6 @@ public class CassandraTemplate extends CqlTemplate implements CassandraOperation
|
||||
* @param entities
|
||||
* @param entity
|
||||
* @param optionsByName
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
public static <T> Batch createDeleteBatchQuery(String tableName, List<T> entities, QueryOptions options,
|
||||
|
||||
@@ -42,7 +42,7 @@ public class BasicCassandraPersistentEntityMetadataVerifier implements Cassandra
|
||||
@Override
|
||||
public void verify(CassandraPersistentEntity<?> entity) throws MappingException {
|
||||
|
||||
VerifierMappingExceptions exceptions = new VerifierMappingExceptions(
|
||||
VerifierMappingExceptions exceptions = new VerifierMappingExceptions(entity,
|
||||
"Mapping Exceptions from BasicCassandraPersistentEntityMetadataVerifier");
|
||||
|
||||
final List<CassandraPersistentProperty> idProperties = new ArrayList<CassandraPersistentProperty>();
|
||||
|
||||
@@ -20,6 +20,7 @@ import java.util.List;
|
||||
import org.springframework.cassandra.core.Ordering;
|
||||
import org.springframework.cassandra.core.cql.CqlIdentifier;
|
||||
import org.springframework.context.ApplicationContextAware;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.data.mapping.PersistentProperty;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
|
||||
@@ -131,4 +132,14 @@ public interface CassandraPersistentProperty extends PersistentProperty<Cassandr
|
||||
* @param columnName
|
||||
*/
|
||||
void setColumnNames(List<CqlIdentifier> columnNames);
|
||||
|
||||
public enum PropertyToFieldNameConverter implements Converter<CassandraPersistentProperty, String> {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public String convert(CassandraPersistentProperty source) {
|
||||
return source.getColumnName().toCql();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,12 +31,14 @@ import org.springframework.data.mapping.model.MappingException;
|
||||
public class VerifierMappingExceptions extends MappingException {
|
||||
|
||||
Collection<MappingException> exceptions = new LinkedList<MappingException>();
|
||||
private String className;
|
||||
|
||||
/**
|
||||
* @param s
|
||||
*/
|
||||
public VerifierMappingExceptions(String s) {
|
||||
public VerifierMappingExceptions(CassandraPersistentEntity<?> entity, String s) {
|
||||
super(s);
|
||||
this.className = entity.getType().getName();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -79,7 +81,7 @@ public class VerifierMappingExceptions extends MappingException {
|
||||
|
||||
@Override
|
||||
public String getMessage() {
|
||||
StringBuilder builder = new StringBuilder();
|
||||
StringBuilder builder = new StringBuilder(className).append(":\n");
|
||||
for (MappingException e : exceptions) {
|
||||
builder.append(e.getMessage()).append("\n");
|
||||
}
|
||||
|
||||
@@ -21,22 +21,25 @@ import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
import org.springframework.data.annotation.QueryAnnotation;
|
||||
|
||||
/**
|
||||
* Annotation to declare finder queries directly on repository methods.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.METHOD)
|
||||
@Documented
|
||||
@QueryAnnotation
|
||||
public @interface Query {
|
||||
|
||||
/**
|
||||
* Takes a Cassandra CQL3 string to define the actual query to be executed.
|
||||
* A Cassandra CQL3 string to define the actual query to be executed. Placeholders {@code ?0}, {@code ?1}, etc are
|
||||
* supported.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,212 @@
|
||||
/*
|
||||
* Copyright 2010-2014 the original author or authors.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.SortedSet;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToBigDecimalConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToBigIntegerConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToBooleanConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToByteBufferConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToDateConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToDoubleConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToFloatConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToInetAddressConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToIntegerConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToListConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToLongConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToStringConverter;
|
||||
import org.springframework.cassandra.core.converter.ResultSetToUuidConverter;
|
||||
import org.springframework.cassandra.core.converter.RowToMapConverter;
|
||||
import org.springframework.core.convert.ConversionService;
|
||||
import org.springframework.core.convert.TypeDescriptor;
|
||||
import org.springframework.core.convert.converter.Converter;
|
||||
import org.springframework.core.convert.support.ConfigurableConversionService;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* Base class for {@link RepositoryQuery} implementations for Cassandra.
|
||||
*/
|
||||
public abstract class AbstractCassandraQuery implements RepositoryQuery {
|
||||
|
||||
protected static final Converter<?, ?>[] DEFAULT_CONVERTERS = new Converter<?, ?>[] { new ResultSetToListConverter(),
|
||||
new ResultSetToStringConverter(), new RowToMapConverter(), new ResultSetToBigDecimalConverter(),
|
||||
new ResultSetToBigIntegerConverter(), new ResultSetToBooleanConverter(), new ResultSetToByteBufferConverter(),
|
||||
new ResultSetToDateConverter(), new ResultSetToDoubleConverter(), new ResultSetToFloatConverter(),
|
||||
new ResultSetToInetAddressConverter(), new ResultSetToIntegerConverter(), new ResultSetToLongConverter(),
|
||||
new ResultSetToUuidConverter() };
|
||||
|
||||
protected static Logger log = LoggerFactory.getLogger(AbstractCassandraQuery.class);
|
||||
|
||||
private ConversionService conversionService;
|
||||
|
||||
Converter<ResultSet, List<Map<String, Object>>> resultSetToListConverter = new ResultSetToListConverter();
|
||||
|
||||
private final CassandraQueryMethod method;
|
||||
private final CassandraOperations template;
|
||||
|
||||
protected RowToMapConverter rowToMapConverter = new RowToMapConverter();
|
||||
|
||||
/**
|
||||
* Creates a new {@link AbstractCassandraQuery} from the given {@link CassandraQueryMethod} and
|
||||
* {@link CassandraOperations}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param template must not be {@literal null}.
|
||||
*/
|
||||
public AbstractCassandraQuery(CassandraQueryMethod method, CassandraOperations operations) {
|
||||
|
||||
Assert.notNull(operations);
|
||||
Assert.notNull(method);
|
||||
|
||||
this.method = method;
|
||||
this.template = operations;
|
||||
|
||||
this.conversionService = createDefaultConversionService();
|
||||
}
|
||||
|
||||
protected ConfigurableConversionService createDefaultConversionService() {
|
||||
|
||||
ConfigurableConversionService conversionService = new DefaultConversionService();
|
||||
|
||||
for (Converter<?, ?> converter : DEFAULT_CONVERTERS) {
|
||||
conversionService.addConverter(converter);
|
||||
}
|
||||
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
@Override
|
||||
public CassandraQueryMethod getQueryMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object execute(Object[] parameters) {
|
||||
|
||||
CassandraParameterAccessor accessor = new CassandraParametersParameterAccessor(method, parameters);
|
||||
String query = createQuery(accessor);
|
||||
|
||||
ResultSet resultSet = template.query(query);
|
||||
|
||||
// return raw result set if requested
|
||||
if (method.isResultSetQuery()) {
|
||||
return resultSet;
|
||||
}
|
||||
|
||||
Class<?> declaredReturnType = method.getReturnType().getType();
|
||||
Class<?> returnedUnwrappedObjectType = method.getReturnedObjectType();
|
||||
|
||||
if (method.isSingleEntityQuery()) {
|
||||
return getSingleEntity(resultSet, returnedUnwrappedObjectType);
|
||||
}
|
||||
|
||||
Object retval = resultSet;
|
||||
|
||||
if (method.isCollectionOfEntityQuery()) {
|
||||
retval = getCollectionOfEntity(resultSet, declaredReturnType, returnedUnwrappedObjectType);
|
||||
}
|
||||
|
||||
// TODO: support Page & Slice queries
|
||||
|
||||
// if we get this far, let the configured conversion service try to convert the result set
|
||||
return conversionService.convert(retval, TypeDescriptor.forObject(retval),
|
||||
TypeDescriptor.valueOf(declaredReturnType));
|
||||
}
|
||||
|
||||
public Object getCollectionOfEntity(ResultSet resultSet, Class<?> declaredReturnType,
|
||||
Class<?> returnedUnwrappedObjectType) {
|
||||
|
||||
Collection<Object> results = null;
|
||||
|
||||
if (ClassUtils.isAssignable(SortedSet.class, declaredReturnType)) {
|
||||
results = new TreeSet<Object>();
|
||||
} else if (ClassUtils.isAssignable(Set.class, declaredReturnType)) {
|
||||
results = new HashSet<Object>();
|
||||
} else { // List.class, Collection.class, or array
|
||||
results = new ArrayList<Object>();
|
||||
}
|
||||
|
||||
CassandraConverter converter = template.getConverter();
|
||||
for (Row row : resultSet) {
|
||||
results.add(converter.read(returnedUnwrappedObjectType, row));
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
public Object getSingleEntity(ResultSet resultSet, Class<?> type) {
|
||||
if (resultSet.isExhausted()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
Object object = template.getConverter().read(type, iterator.next());
|
||||
|
||||
warnIfMoreResults(iterator);
|
||||
|
||||
return object;
|
||||
}
|
||||
|
||||
protected void warnIfMoreResults(Iterator<Row> iterator) {
|
||||
if (log.isWarnEnabled() && iterator.hasNext()) {
|
||||
|
||||
int i = 0;
|
||||
while (iterator.hasNext()) {
|
||||
iterator.next();
|
||||
i++;
|
||||
}
|
||||
|
||||
log.warn("ignoring extra {} row{}", i, i == 1 ? "" : "s");
|
||||
}
|
||||
}
|
||||
|
||||
public ConversionService getConversionService() {
|
||||
return conversionService;
|
||||
}
|
||||
|
||||
public void setConversionService(ConversionService conversionService) {
|
||||
|
||||
Assert.notNull(conversionService);
|
||||
this.conversionService = conversionService;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a string query using the given {@link ParameterAccessor}
|
||||
*
|
||||
* @param accessor must not be {@literal null}.
|
||||
*/
|
||||
protected abstract String createQuery(CassandraParameterAccessor accessor);
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import org.springframework.data.repository.query.ParameterAccessor;
|
||||
|
||||
public interface CassandraParameterAccessor extends ParameterAccessor {
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.List;
|
||||
|
||||
import org.springframework.core.MethodParameter;
|
||||
import org.springframework.data.repository.query.Parameter;
|
||||
import org.springframework.data.repository.query.Parameters;
|
||||
|
||||
public class CassandraParameters extends Parameters<CassandraParameters, Parameter> {
|
||||
|
||||
public CassandraParameters(List<Parameter> originals) {
|
||||
super(originals);
|
||||
}
|
||||
|
||||
public CassandraParameters(Method method) {
|
||||
super(method);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CassandraParameter createParameter(MethodParameter parameter) {
|
||||
return new CassandraParameter(parameter);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CassandraParameters createFrom(List<Parameter> parameters) {
|
||||
return new CassandraParameters(parameters);
|
||||
}
|
||||
|
||||
class CassandraParameter extends Parameter {
|
||||
|
||||
protected CassandraParameter(MethodParameter parameter) {
|
||||
super(parameter);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import org.springframework.data.repository.query.ParametersParameterAccessor;
|
||||
|
||||
public class CassandraParametersParameterAccessor extends ParametersParameterAccessor implements
|
||||
CassandraParameterAccessor {
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraParametersParameterAccessor}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param values must not be {@@iteral null}.
|
||||
*/
|
||||
public CassandraParametersParameterAccessor(CassandraQueryMethod method, Object... values) {
|
||||
super(method.getParameters(), values);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,220 @@
|
||||
/*
|
||||
* Copyright 2010-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.repository.query;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.domain.Sort;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.mapping.context.PersistentPropertyPath;
|
||||
import org.springframework.data.repository.query.parser.AbstractQueryCreator;
|
||||
import org.springframework.data.repository.query.parser.Part;
|
||||
import org.springframework.data.repository.query.parser.Part.IgnoreCaseType;
|
||||
import org.springframework.data.repository.query.parser.Part.Type;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.querybuilder.Clause;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* Custom query creator to create Cassandra criteria.
|
||||
*/
|
||||
class CassandraQueryCreator extends AbstractQueryCreator<Select, Clause> {
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CassandraQueryCreator.class);
|
||||
private final CassandraParameterAccessor accessor;
|
||||
|
||||
private final CassandraMappingContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link CassandraQueryCreator} from the given {@link PartTree}, {@link ConvertingParameterAccessor}
|
||||
* and {@link MappingContext}.
|
||||
*
|
||||
* @param tree
|
||||
* @param accessor
|
||||
* @param context
|
||||
*/
|
||||
public CassandraQueryCreator(PartTree tree, CassandraParameterAccessor accessor, CassandraMappingContext context) {
|
||||
|
||||
super(tree, accessor);
|
||||
|
||||
Assert.notNull(context);
|
||||
|
||||
this.accessor = accessor;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Clause create(Part part, Iterator<Object> iterator) {
|
||||
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
|
||||
CassandraPersistentProperty property = path.getLeafProperty();
|
||||
Clause criteria = from(part, property,
|
||||
null /* TODO where(path.toDotPath(CassandraPersistentProperty.PropertyToFieldNameConverter.INSTANCE))*/,
|
||||
iterator);
|
||||
|
||||
return criteria;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Clause and(Part part, Clause base, Iterator<Object> iterator) {
|
||||
|
||||
if (base == null) {
|
||||
return create(part, iterator);
|
||||
}
|
||||
|
||||
PersistentPropertyPath<CassandraPersistentProperty> path = context.getPersistentPropertyPath(part.getProperty());
|
||||
CassandraPersistentProperty property = path.getLeafProperty();
|
||||
|
||||
return from(part, property,
|
||||
null /* TODO base.and(path.toDotPath(CassandraPersistentProperty.PropertyToFieldNameConverter.INSTANCE))*/,
|
||||
iterator);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Clause or(Clause base, Clause criteria) {
|
||||
throw new InvalidDataAccessApiUsageException(String.format("Cassandra does not support an OR operator!"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Select complete(Clause criteria, Sort sort) {
|
||||
|
||||
if (criteria == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Select select = QueryBuilder.select().all().from("TODO");
|
||||
select.where(criteria);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Created query " + select.getQueryString());
|
||||
}
|
||||
|
||||
return select;
|
||||
}
|
||||
|
||||
private Clause from(Part part, CassandraPersistentProperty property, Clause criteria, Iterator<Object> parameters) {
|
||||
|
||||
Type type = part.getType();
|
||||
|
||||
switch (type) {
|
||||
// TODO
|
||||
// case AFTER:
|
||||
// case GREATER_THAN:
|
||||
// return criteria.gt(parameters.nextConverted(property));
|
||||
// case GREATER_THAN_EQUAL:
|
||||
// return criteria.gte(parameters.nextConverted(property));
|
||||
// case BEFORE:
|
||||
// case LESS_THAN:
|
||||
// return criteria.lt(parameters.nextConverted(property));
|
||||
// case LESS_THAN_EQUAL:
|
||||
// return criteria.lte(parameters.nextConverted(property));
|
||||
// case BETWEEN:
|
||||
// return criteria.gt(parameters.nextConverted(property)).lt(parameters.nextConverted(property));
|
||||
// case IS_NOT_NULL:
|
||||
// return criteria.ne(null);
|
||||
// case IS_NULL:
|
||||
// return criteria.is(null);
|
||||
// case NOT_IN:
|
||||
// return criteria.nin(nextAsArray(parameters, property));
|
||||
// case IN:
|
||||
// return criteria.in(nextAsArray(parameters, property));
|
||||
// case LIKE:
|
||||
// case STARTING_WITH:
|
||||
// case ENDING_WITH:
|
||||
// case CONTAINING:
|
||||
// return addAppropriateLikeRegexTo(criteria, part, parameters.next().toString());
|
||||
// case REGEX:
|
||||
// return criteria.regex(parameters.next().toString());
|
||||
// case EXISTS:
|
||||
// return criteria.exists((Boolean) parameters.next());
|
||||
// case TRUE:
|
||||
// return criteria.is(true);
|
||||
// case FALSE:
|
||||
// return criteria.is(false);
|
||||
// case WITHIN:
|
||||
//
|
||||
// Object parameter = parameters.next();
|
||||
// return criteria.within((Shape) parameter);
|
||||
// case SIMPLE_PROPERTY:
|
||||
//
|
||||
// return isSimpleComparisionPossible(part) ? criteria.is(parameters.nextConverted(property))
|
||||
// : createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, false);
|
||||
//
|
||||
// case NEGATING_SIMPLE_PROPERTY:
|
||||
//
|
||||
// return isSimpleComparisionPossible(part) ? criteria.ne(parameters.nextConverted(property))
|
||||
// : createLikeRegexCriteriaOrThrow(part, property, criteria, parameters, true);
|
||||
default:
|
||||
throw new UnsupportedCassandraQueryOperatorException(String.format(""));
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isSimpleComparisionPossible(Part part) {
|
||||
|
||||
switch (part.shouldIgnoreCase()) {
|
||||
case NEVER:
|
||||
return true;
|
||||
case WHEN_POSSIBLE:
|
||||
return part.getProperty().getType() != String.class;
|
||||
case ALWAYS:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the next element from the given {@link Iterator} expecting it to be of a certain type.
|
||||
*
|
||||
* @param <T>
|
||||
* @param iterator
|
||||
* @param type
|
||||
* @throws IllegalArgumentException in case the next element in the iterator is not of the given type.
|
||||
* @return
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T nextAs(Iterator<Object> iterator, Class<T> type) {
|
||||
Object parameter = iterator.next();
|
||||
if (parameter.getClass().isAssignableFrom(type)) {
|
||||
return (T) parameter;
|
||||
}
|
||||
|
||||
throw new IllegalArgumentException(String.format("Expected parameter type of %s but got %s!", type,
|
||||
parameter.getClass()));
|
||||
}
|
||||
|
||||
private Object[] nextAsArray(Iterator<Object> iterator, CassandraPersistentProperty property) {
|
||||
Object next = iterator.next(); // TODO nextConverted(property);
|
||||
|
||||
if (next instanceof Collection) {
|
||||
return ((Collection<?>) next).toArray();
|
||||
} else if (next.getClass().isArray()) {
|
||||
return (Object[]) next;
|
||||
}
|
||||
|
||||
return new Object[] { next };
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,156 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.net.InetAddress;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.UUID;
|
||||
|
||||
import org.springframework.core.annotation.AnnotationUtils;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.cassandra.repository.Query;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.util.ClassTypeInformation;
|
||||
import org.springframework.data.util.TypeInformation;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ClassUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
public class CassandraQueryMethod extends QueryMethod {
|
||||
|
||||
// TODO: double-check this list
|
||||
public static final List<Class<?>> ALLOWED_PARAMETER_TYPES = Collections.unmodifiableList(Arrays
|
||||
.asList(new Class<?>[] { String.class, CharSequence.class, char.class, Character.class, char[].class, long.class,
|
||||
Long.class, boolean.class, Boolean.class, BigDecimal.class, BigInteger.class, double.class, Double.class,
|
||||
float.class, Float.class, InetAddress.class, Date.class, UUID.class, }));
|
||||
|
||||
public static boolean isMapOfCharSequenceToObject(TypeInformation<?> type) {
|
||||
|
||||
if (!type.isMap()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
TypeInformation<?> keyType = type.getComponentType();
|
||||
TypeInformation<?> valueType = type.getMapValueType();
|
||||
|
||||
return ClassUtils.isAssignable(CharSequence.class, keyType.getType()) && Object.class.equals(valueType.getType());
|
||||
}
|
||||
|
||||
protected Method method;
|
||||
protected CassandraMappingContext mappingContext;
|
||||
protected Query query;
|
||||
protected String queryString;
|
||||
protected boolean queryCached = false;
|
||||
|
||||
public CassandraQueryMethod(Method method, RepositoryMetadata metadata, CassandraMappingContext mappingContext) {
|
||||
|
||||
super(method, metadata);
|
||||
|
||||
verify(method, metadata);
|
||||
|
||||
this.method = method;
|
||||
|
||||
Assert.notNull(mappingContext, "MappingContext must not be null!");
|
||||
this.mappingContext = mappingContext;
|
||||
}
|
||||
|
||||
public void verify(Method method, RepositoryMetadata metadata) {
|
||||
|
||||
// TODO: support Page & Slice queries
|
||||
if (isSliceQuery() || isPageQuery()) {
|
||||
throw new InvalidDataAccessApiUsageException("neither slice nor page queries are supported yet");
|
||||
}
|
||||
|
||||
Set<Class<?>> offendingTypes = new HashSet<Class<?>>();
|
||||
for (Class<?> type : method.getParameterTypes()) {
|
||||
if (!ALLOWED_PARAMETER_TYPES.contains(type)) {
|
||||
offendingTypes.add(type);
|
||||
}
|
||||
}
|
||||
|
||||
if (offendingTypes.size() > 0) {
|
||||
throw new IllegalArgumentException(String.format(
|
||||
"encountered unsupported query parameter type%s [%s] in method %s", offendingTypes.size() == 1 ? "" : "s",
|
||||
StringUtils.arrayToCommaDelimitedString(new ArrayList<Class<?>>(offendingTypes).toArray()), method));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected CassandraParameters createParameters(Method method) {
|
||||
return new CassandraParameters(method);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the {@link Query} annotation that is applied to the method or {@code null} if none available.
|
||||
*/
|
||||
Query getQueryAnnotation() {
|
||||
if (query == null) {
|
||||
query = method.getAnnotation(Query.class);
|
||||
queryCached = true;
|
||||
}
|
||||
return query;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether the method has an annotated query.
|
||||
*/
|
||||
public boolean hasAnnotatedQuery() {
|
||||
return getAnnotatedQuery() != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the query string declared in a {@link Query} annotation or {@literal null} if neither the annotation found
|
||||
* nor the attribute was specified.
|
||||
*/
|
||||
public String getAnnotatedQuery() {
|
||||
|
||||
if (!queryCached) {
|
||||
queryString = (String) AnnotationUtils.getValue(getQueryAnnotation());
|
||||
queryString = StringUtils.hasText(queryString) ? queryString : null;
|
||||
}
|
||||
|
||||
return queryString;
|
||||
}
|
||||
|
||||
public TypeInformation<?> getReturnType() {
|
||||
return ClassTypeInformation.fromReturnTypeOf(method);
|
||||
}
|
||||
|
||||
public boolean isResultSetQuery() {
|
||||
return ResultSet.class.isAssignableFrom(method.getReturnType());
|
||||
}
|
||||
|
||||
public boolean isSingleEntityQuery() {
|
||||
return ClassUtils.isAssignable(getDomainClass(), method.getReturnType());
|
||||
}
|
||||
|
||||
public boolean isCollectionOfEntityQuery() {
|
||||
return isQueryForEntity() && isCollectionQuery();
|
||||
}
|
||||
|
||||
public boolean isMapOfCharSequenceToObjectQuery() {
|
||||
|
||||
return isMapOfCharSequenceToObject(getReturnType());
|
||||
}
|
||||
|
||||
public boolean isListOfMapOfCharSequenceToObject() {
|
||||
|
||||
TypeInformation<?> type = getReturnType();
|
||||
if (!ClassUtils.isAssignable(List.class, type.getType())) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return isMapOfCharSequenceToObject(type.getComponentType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 2002-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.repository.query;
|
||||
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.core.CassandraTemplate;
|
||||
import org.springframework.data.cassandra.mapping.CassandraMappingContext;
|
||||
import org.springframework.data.repository.query.QueryMethod;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.data.repository.query.parser.PartTree;
|
||||
|
||||
/**
|
||||
* {@link RepositoryQuery} implementation for Cassandra.
|
||||
*
|
||||
*/
|
||||
public class PartTreeCassandraQuery extends AbstractCassandraQuery {
|
||||
|
||||
private final PartTree tree;
|
||||
private final CassandraMappingContext context;
|
||||
|
||||
/**
|
||||
* Creates a new {@link PartTreeCassandraQuery} from the given {@link QueryMethod} and {@link CassandraTemplate}.
|
||||
*
|
||||
* @param method must not be {@literal null}.
|
||||
* @param template must not be {@literal null}.
|
||||
*/
|
||||
public PartTreeCassandraQuery(CassandraQueryMethod method, CassandraOperations cassandraOperations) {
|
||||
|
||||
super(method, cassandraOperations);
|
||||
this.tree = new PartTree(method.getName(), method.getEntityInformation().getJavaType());
|
||||
this.context = cassandraOperations.getConverter().getMappingContext();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the {@link PartTree} backing the query.
|
||||
*
|
||||
* @return the tree
|
||||
*/
|
||||
public PartTree getTree() {
|
||||
return tree;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String createQuery(CassandraParameterAccessor accessor) {
|
||||
|
||||
CassandraQueryCreator creator = new CassandraQueryCreator(tree, accessor, context);
|
||||
return creator.createQuery().getQueryString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
|
||||
public class StringBasedCassandraQuery extends AbstractCassandraQuery {
|
||||
|
||||
private static final Pattern PLACEHOLDER = Pattern.compile("\\?(\\d+)");
|
||||
private static final Logger LOG = LoggerFactory.getLogger(StringBasedCassandraQuery.class);
|
||||
|
||||
protected String query;
|
||||
|
||||
public StringBasedCassandraQuery(String query, CassandraQueryMethod queryMethod, CassandraOperations operations) {
|
||||
|
||||
super(queryMethod, operations);
|
||||
|
||||
this.query = query;
|
||||
}
|
||||
|
||||
public StringBasedCassandraQuery(CassandraQueryMethod queryMethod, CassandraOperations operations) {
|
||||
this(queryMethod.getAnnotatedQuery(), queryMethod, operations);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String createQuery(CassandraParameterAccessor accessor) {
|
||||
return replacePlaceholders(query, accessor);
|
||||
}
|
||||
|
||||
private String replacePlaceholders(String input, CassandraParameterAccessor accessor) {
|
||||
|
||||
Matcher matcher = PLACEHOLDER.matcher(input);
|
||||
String result = input;
|
||||
|
||||
while (matcher.find()) {
|
||||
String group = matcher.group();
|
||||
int index = Integer.parseInt(matcher.group(1));
|
||||
result = result.replace(group, getParameterWithIndex(accessor, index).toString());
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object getParameterWithIndex(CassandraParameterAccessor accessor, int index) {
|
||||
return accessor.getBindableValue(index);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package org.springframework.data.cassandra.repository.query;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
|
||||
public class UnsupportedCassandraQueryOperatorException extends InvalidDataAccessApiUsageException {
|
||||
|
||||
public UnsupportedCassandraQueryOperatorException(String msg) {
|
||||
super(msg);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
public UnsupportedCassandraQueryOperatorException(String msg, Throwable cause) {
|
||||
super(msg, cause);
|
||||
// TODO Auto-generated constructor stub
|
||||
}
|
||||
|
||||
}
|
||||
@@ -16,16 +16,23 @@
|
||||
package org.springframework.data.cassandra.repository.support;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.data.cassandra.core.CassandraTemplate;
|
||||
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.repository.TypedIdCassandraRepository;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraEntityInformation;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryMethod;
|
||||
import org.springframework.data.cassandra.repository.query.StringBasedCassandraQuery;
|
||||
import org.springframework.data.mapping.model.MappingException;
|
||||
import org.springframework.data.repository.core.NamedQueries;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
import org.springframework.data.repository.core.support.RepositoryFactorySupport;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy;
|
||||
import org.springframework.data.repository.query.QueryLookupStrategy.Key;
|
||||
import org.springframework.data.repository.query.RepositoryQuery;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
@@ -38,7 +45,7 @@ import org.springframework.util.Assert;
|
||||
public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
private final CassandraTemplate cassandraTemplate;
|
||||
private final MappingContext<? extends CassandraPersistentEntity<?>, CassandraPersistentProperty> mappingContext;
|
||||
private final CassandraMappingContext mappingContext;
|
||||
|
||||
/**
|
||||
* Creates a new {@link MongoRepositoryFactory} with the given {@link MongoOperations}.
|
||||
@@ -51,6 +58,9 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
|
||||
this.cassandraTemplate = cassandraTemplate;
|
||||
this.mappingContext = cassandraTemplate.getConverter().getMappingContext();
|
||||
|
||||
// TODO: remove when supporting declarative query methods
|
||||
setQueryLookupStrategyKey(QueryLookupStrategy.Key.USE_DECLARED_QUERY);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -82,4 +92,28 @@ public class CassandraRepositoryFactory extends RepositoryFactorySupport {
|
||||
return new MappingCassandraEntityInformation<T, ID>((CassandraPersistentEntity<T>) entity,
|
||||
cassandraTemplate.getConverter());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected QueryLookupStrategy getQueryLookupStrategy(Key key) {
|
||||
return new CassandraQueryLookupStrategy();
|
||||
}
|
||||
|
||||
private class CassandraQueryLookupStrategy implements QueryLookupStrategy {
|
||||
|
||||
@Override
|
||||
public RepositoryQuery resolveQuery(Method method, RepositoryMetadata metadata, NamedQueries namedQueries) {
|
||||
|
||||
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method, metadata, mappingContext);
|
||||
String namedQueryName = queryMethod.getNamedQueryName();
|
||||
|
||||
if (namedQueries.hasQuery(namedQueryName)) {
|
||||
String namedQuery = namedQueries.getQuery(namedQueryName);
|
||||
return new StringBasedCassandraQuery(namedQuery, queryMethod, cassandraTemplate);
|
||||
} else if (queryMethod.hasAnnotatedQuery()) {
|
||||
return new StringBasedCassandraQuery(queryMethod, cassandraTemplate);
|
||||
} else {
|
||||
throw new InvalidDataAccessApiUsageException("declarative query methods are a todo");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010-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.querymethods.declared;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
import org.springframework.cassandra.core.PrimaryKeyType;
|
||||
import org.springframework.data.cassandra.mapping.PrimaryKeyColumn;
|
||||
import org.springframework.data.cassandra.mapping.Table;
|
||||
|
||||
/**
|
||||
* Sample domain class.
|
||||
*/
|
||||
@Table
|
||||
public class Person {
|
||||
|
||||
@PrimaryKeyColumn(type = PrimaryKeyType.PARTITIONED, ordinal = 0)
|
||||
private String lastname;
|
||||
|
||||
@PrimaryKeyColumn(type = PrimaryKeyType.CLUSTERED, ordinal = 1)
|
||||
private String firstname;
|
||||
|
||||
private String nickname;
|
||||
|
||||
private Date birthDate;
|
||||
|
||||
private int numberOfChildren;
|
||||
|
||||
private boolean cool;
|
||||
|
||||
// TODO: private UUID uuid = UUID.randomUUID();
|
||||
|
||||
public String getFirstname() {
|
||||
return firstname;
|
||||
}
|
||||
|
||||
public void setFirstname(String firstname) {
|
||||
this.firstname = firstname;
|
||||
}
|
||||
|
||||
public String getLastname() {
|
||||
return lastname;
|
||||
}
|
||||
|
||||
public void setLastname(String lastname) {
|
||||
this.lastname = lastname;
|
||||
}
|
||||
|
||||
public String getNickname() {
|
||||
return nickname;
|
||||
}
|
||||
|
||||
public void setNickname(String nickname) {
|
||||
this.nickname = nickname;
|
||||
}
|
||||
|
||||
public Date getBirthDate() {
|
||||
return new Date(birthDate.getTime());
|
||||
}
|
||||
|
||||
public void setBirthDate(Date birthDate) {
|
||||
this.birthDate = birthDate == null ? null : new Date(birthDate.getTime());
|
||||
}
|
||||
|
||||
public int getNumberOfChildren() {
|
||||
return numberOfChildren;
|
||||
}
|
||||
|
||||
public void setNumberOfChildren(int numberOfChildren) {
|
||||
this.numberOfChildren = numberOfChildren;
|
||||
}
|
||||
|
||||
public boolean isCool() {
|
||||
return cool;
|
||||
}
|
||||
|
||||
public void setCool(boolean cool) {
|
||||
this.cool = cool;
|
||||
}
|
||||
|
||||
// public UUID getUuid() {
|
||||
// return uuid;
|
||||
// }
|
||||
//
|
||||
// public void setUuid(UUID uuid) {
|
||||
// this.uuid = uuid;
|
||||
// }
|
||||
}
|
||||
@@ -0,0 +1,251 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.cassandra.config.SchemaAction;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.base.PersonRepository;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class QueryIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
|
||||
|
||||
public static class Config extends IntegrationTestConfig {
|
||||
|
||||
@Override
|
||||
public String[] getEntityBasePackages() {
|
||||
return new String[] { Person.class.getPackage().getName() };
|
||||
}
|
||||
|
||||
@Override
|
||||
public SchemaAction getSchemaAction() {
|
||||
return SchemaAction.RECREATE_DROP_UNUSED;
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
PersonRepository r;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
deleteAllEntities();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListMethodSingleResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
List<Person> results = r.findFolksWithLastnameAsList(saved.getLastname());
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.size() == 1);
|
||||
Person found = results.iterator().next();
|
||||
assertNotNull(found);
|
||||
assertEquals(found.getLastname(), saved.getLastname());
|
||||
assertEquals(found.getFirstname(), saved.getFirstname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListMethodMultipleResults() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname("a");
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
Person saved2 = new Person();
|
||||
saved2.setFirstname("b");
|
||||
saved2.setLastname(saved.getLastname());
|
||||
|
||||
saved2 = r.save(saved2);
|
||||
|
||||
List<Person> results = r.findFolksWithLastnameAsList(saved.getLastname());
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.size() == 2);
|
||||
boolean first = true;
|
||||
for (Person person : results) {
|
||||
assertNotNull(person);
|
||||
assertEquals(saved.getLastname(), person.getLastname());
|
||||
assertEquals(first ? saved.getFirstname() : saved2.getFirstname(), person.getFirstname());
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListOfMapOfStringToObjectMethodSingleResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
List<Map<String, Object>> results = r.findFolksWithLastnameAsListOfMapOfStringToObject(saved.getLastname());
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.size() == 1);
|
||||
Map<String, Object> found = results.iterator().next();
|
||||
assertNotNull(found);
|
||||
assertEquals(found.get("lastname"), saved.getLastname());
|
||||
assertEquals(found.get("firstname"), saved.getFirstname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntityMethodResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
Person found = r.findSingle(saved.getLastname(), saved.getFirstname());
|
||||
|
||||
assertNotNull(found);
|
||||
assertEquals(found.getLastname(), saved.getLastname());
|
||||
assertEquals(found.getFirstname(), saved.getFirstname());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testListOfMapOfStringToObjectMethodMultipleResults() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname("a");
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
Person saved2 = new Person();
|
||||
saved2.setFirstname("b");
|
||||
saved2.setLastname(saved.getLastname());
|
||||
|
||||
saved2 = r.save(saved2);
|
||||
|
||||
Collection<Person> results = r.findFolksWithLastnameAsList(saved.getLastname());
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.size() == 2);
|
||||
boolean first = true;
|
||||
for (Person person : results) {
|
||||
assertNotNull(person);
|
||||
assertEquals(saved.getLastname(), person.getLastname());
|
||||
assertEquals(first ? saved.getFirstname() : saved2.getFirstname(), person.getFirstname());
|
||||
first = false;
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStringMethodResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
saved.setNickname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
String nickname = r.findSingleNickname(saved.getLastname(), saved.getFirstname());
|
||||
|
||||
assertNotNull(nickname);
|
||||
assertEquals(saved.getNickname(), nickname);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBooleanMethodResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
saved.setCool(true);
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
boolean value = r.findSingleCool(saved.getLastname(), saved.getFirstname());
|
||||
|
||||
assertEquals(saved.isCool(), value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDateMethodResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
saved.setBirthDate(new Date());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
Date value = r.findSingleBirthdate(saved.getLastname(), saved.getFirstname());
|
||||
|
||||
assertEquals(saved.getBirthDate(), value);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIntMethodResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
saved.setNumberOfChildren(1);
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
int value = r.findSingleNumberOfChildren(saved.getLastname(), saved.getFirstname());
|
||||
|
||||
assertEquals(saved.getNumberOfChildren(), value);
|
||||
}
|
||||
|
||||
// TODO: @Test
|
||||
// public void testUuidMethodResult() {
|
||||
//
|
||||
// Person saved = new Person();
|
||||
// saved.setFirstname(uuid());
|
||||
// saved.setLastname(uuid());
|
||||
// saved.setUuid(UUID.randomUUID());
|
||||
//
|
||||
// saved = r.save(saved);
|
||||
//
|
||||
// UUID value = r.findSingleUuid(saved.getLastname(), saved.getFirstname());
|
||||
//
|
||||
// assertEquals(saved.getUuid(), value);
|
||||
// }
|
||||
|
||||
@Test
|
||||
public void testArrayMethodSingleResult() {
|
||||
|
||||
Person saved = new Person();
|
||||
saved.setFirstname(uuid());
|
||||
saved.setLastname(uuid());
|
||||
|
||||
saved = r.save(saved);
|
||||
|
||||
Person[] results = r.findFolksWithLastnameAsArray(saved.getLastname());
|
||||
|
||||
assertNotNull(results);
|
||||
assertTrue(results.length == 1);
|
||||
Person found = results[0];
|
||||
assertNotNull(found);
|
||||
assertEquals(found.getLastname(), saved.getLastname());
|
||||
assertEquals(found.getFirstname(), saved.getFirstname());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* 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.querymethods.declared;
|
||||
|
||||
import static org.hamcrest.Matchers.is;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.mockito.Mockito.when;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.runners.MockitoJUnitRunner;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.convert.MappingCassandraConverter;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.mapping.BasicCassandraMappingContext;
|
||||
import org.springframework.data.cassandra.repository.Query;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraParametersParameterAccessor;
|
||||
import org.springframework.data.cassandra.repository.query.CassandraQueryMethod;
|
||||
import org.springframework.data.cassandra.repository.query.StringBasedCassandraQuery;
|
||||
import org.springframework.data.repository.core.RepositoryMetadata;
|
||||
|
||||
import com.datastax.driver.core.SimpleStatement;
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* Unit tests for {@link StringBasedCassandraQuery}.
|
||||
*/
|
||||
@RunWith(MockitoJUnitRunner.class)
|
||||
public class StringBasedCassandraQueryIntegrationTests {
|
||||
|
||||
@Mock
|
||||
CassandraOperations operations;
|
||||
@Mock
|
||||
RepositoryMetadata metadata;
|
||||
|
||||
CassandraConverter converter;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
|
||||
when(operations.getConverter()).thenReturn(converter);
|
||||
|
||||
this.converter = new MappingCassandraConverter(new BasicCassandraMappingContext());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindsSimplePropertyCorrectly() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastname", String.class);
|
||||
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method, metadata, converter.getMappingContext());
|
||||
StringBasedCassandraQuery cassandraQuery = new StringBasedCassandraQuery(queryMethod, operations);
|
||||
CassandraParametersParameterAccessor accesor = new CassandraParametersParameterAccessor(queryMethod, "Matthews");
|
||||
|
||||
String stringQuery = cassandraQuery.createQuery(accesor);
|
||||
SimpleStatement actual = new SimpleStatement(stringQuery);
|
||||
|
||||
String table = Person.class.getSimpleName().toLowerCase();
|
||||
Select expected = QueryBuilder.select().all().from(table);
|
||||
expected.where(QueryBuilder.eq("lastname", "Matthews"));
|
||||
|
||||
assertThat(actual.getQueryString(), is(expected.getQueryString()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void bindsMultipleParametersCorrectly() throws Exception {
|
||||
|
||||
Method method = SampleRepository.class.getMethod("findByLastnameAndFirstname", String.class, String.class);
|
||||
CassandraQueryMethod queryMethod = new CassandraQueryMethod(method, metadata, converter.getMappingContext());
|
||||
StringBasedCassandraQuery cassandraQuery = new StringBasedCassandraQuery(queryMethod, operations);
|
||||
CassandraParametersParameterAccessor accesor = new CassandraParametersParameterAccessor(queryMethod, "Matthews",
|
||||
"John");
|
||||
|
||||
String stringQuery = cassandraQuery.createQuery(accesor);
|
||||
SimpleStatement actual = new SimpleStatement(stringQuery);
|
||||
|
||||
String table = Person.class.getSimpleName().toLowerCase();
|
||||
Select expected = QueryBuilder.select().all().from(table);
|
||||
expected.where(QueryBuilder.eq("lastname", "Matthews")).and(QueryBuilder.eq("firstname", "John"));
|
||||
|
||||
assertThat(actual.getQueryString(), is(expected.getQueryString()));
|
||||
}
|
||||
|
||||
private interface SampleRepository {
|
||||
|
||||
@Query("SELECT * FROM person WHERE lastname='?0';")
|
||||
Person findByLastname(String lastname);
|
||||
|
||||
@Query("SELECT * FROM person WHERE lastname='?0' AND firstname='?1';")
|
||||
Person findByLastnameAndFirstname(String lastname, String firstname);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared.anno;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.cassandra.repository.Query;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.Person;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.base.PersonRepository;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.named.PersonRepositoryWithNamedQueries;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
/**
|
||||
* we extend {@link PersonRepositoryWithNamedQueries} here just to keep the test codebase in sync.
|
||||
*/
|
||||
public interface PersonRepositoryWithQueryAnnotations extends PersonRepository {
|
||||
|
||||
@Override
|
||||
@Query("select * from person where lastname = '?0'")
|
||||
List<Person> findFolksWithLastnameAsList(String lastname);
|
||||
|
||||
@Override
|
||||
@Query("select * from person where lastname = '?0'")
|
||||
ResultSet findFolksWithLastnameAsResultSet(String last);
|
||||
|
||||
@Override
|
||||
@Query("select * from person where lastname = '?0'")
|
||||
Person[] findFolksWithLastnameAsArray(String lastname);
|
||||
|
||||
@Override
|
||||
@Query("select * from person where lastname = '?0' and firstname = '?1'")
|
||||
Person findSingle(String last, String first);
|
||||
|
||||
@Override
|
||||
@Query("select * from person where lastname = '?0'")
|
||||
List<Map<String, Object>> findFolksWithLastnameAsListOfMapOfStringToObject(String last);
|
||||
|
||||
@Override
|
||||
@Query("select nickname from person where lastname = '?0' and firstname = '?1'")
|
||||
String findSingleNickname(String last, String first);
|
||||
|
||||
@Override
|
||||
@Query("select birthdate from person where lastname = '?0' and firstname = '?1'")
|
||||
Date findSingleBirthdate(String last, String first);
|
||||
|
||||
@Override
|
||||
@Query("select cool from person where lastname = '?0' and firstname = '?1'")
|
||||
boolean findSingleCool(String last, String first);
|
||||
|
||||
@Override
|
||||
@Query("select numberofchildren from person where lastname = '?0' and firstname = '?1'")
|
||||
int findSingleNumberOfChildren(String last, String first);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared.anno;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.QueryIntegrationTests;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ContextConfiguration
|
||||
public class QueryAnnotationIntegrationTests extends QueryIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCassandraRepositories(basePackageClasses = PersonRepositoryWithQueryAnnotations.class)
|
||||
public static class Config extends QueryIntegrationTests.Config {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared.base;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.data.cassandra.repository.CassandraRepository;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.Person;
|
||||
import org.springframework.data.repository.NoRepositoryBean;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
|
||||
@NoRepositoryBean
|
||||
public interface PersonRepository extends CassandraRepository<Person> {
|
||||
|
||||
List<Person> findFolksWithLastnameAsList(String lastname);
|
||||
|
||||
ResultSet findFolksWithLastnameAsResultSet(String last);
|
||||
|
||||
Person[] findFolksWithLastnameAsArray(String lastname);
|
||||
|
||||
Person findSingle(String last, String first);
|
||||
|
||||
List<Map<String, Object>> findFolksWithLastnameAsListOfMapOfStringToObject(String last);
|
||||
|
||||
String findSingleNickname(String last, String first);
|
||||
|
||||
Date findSingleBirthdate(String last, String first);
|
||||
|
||||
boolean findSingleCool(String last, String first);
|
||||
|
||||
int findSingleNumberOfChildren(String last, String first);
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared.named;
|
||||
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.QueryIntegrationTests;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
|
||||
@ContextConfiguration
|
||||
public class NamedQueryIntegrationTests extends QueryIntegrationTests {
|
||||
|
||||
@Configuration
|
||||
@EnableCassandraRepositories(basePackageClasses = PersonRepositoryWithNamedQueries.class, namedQueriesLocation = "classpath:META-INF/PersonRepositoryWithNamedQueries.properties")
|
||||
public static class Config extends QueryIntegrationTests.Config {
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.declared.named;
|
||||
|
||||
import org.springframework.data.cassandra.test.integration.querymethods.declared.base.PersonRepository;
|
||||
|
||||
public interface PersonRepositoryWithNamedQueries extends PersonRepository {
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
package org.springframework.data.cassandra.test.integration.querymethods.derived;
|
||||
|
||||
// TODO
|
||||
public class TODO {
|
||||
}
|
||||
@@ -21,7 +21,9 @@ import org.springframework.data.cassandra.repository.TypedIdCassandraRepository;
|
||||
* Sample repository managing {@link User} entities.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
public interface UserRepository extends TypedIdCassandraRepository<User, String> {
|
||||
|
||||
String findByNamedQuery(String username);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,12 @@ public class UserRepositoryIntegrationTests {
|
||||
setUp();
|
||||
}
|
||||
|
||||
public void findByNamedQuery() {
|
||||
String name = repository.findByNamedQuery("bob");
|
||||
Assert.assertNotNull(name);
|
||||
Assert.assertEquals("Bob", name);
|
||||
}
|
||||
|
||||
public void findsUserById() throws Exception {
|
||||
|
||||
User user = repository.findOne(bob.getUsername());
|
||||
|
||||
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* Copyright 2013-2014 the original author or authors
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.data.cassandra.test.integration.repository;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Base class for Java config tests for {@link UserRepository}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
public abstract class UserRepositoryIntegrationTestsDelegator extends
|
||||
AbstractSpringDataEmbeddedCassandraIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected UserRepository repository;
|
||||
|
||||
@Autowired
|
||||
protected CassandraOperations template;
|
||||
|
||||
UserRepositoryIntegrationTests tests;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
tests = new UserRepositoryIntegrationTests(repository, template);
|
||||
tests.before();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findByNamedQuery() {
|
||||
tests.findByNamedQuery();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsUserById() throws Exception {
|
||||
tests.findsUserById();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAll() throws Exception {
|
||||
tests.findsAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAllWithGivenIds() {
|
||||
tests.findsAllWithGivenIds();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserCorrectly() throws Exception {
|
||||
tests.deletesUserCorrectly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserByIdCorrectly() {
|
||||
tests.deletesUserByIdCorrectly();
|
||||
}
|
||||
}
|
||||
@@ -15,26 +15,18 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.test.integration.repository;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.repository.config.EnableCassandraRepositories;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.data.cassandra.test.integration.support.IntegrationTestConfig;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Base class for Java config tests for {@link UserRepository}.
|
||||
* Java config tests for {@link UserRepository}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class UserRepositoryJavaConfigIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
|
||||
public class UserRepositoryJavaConfigIntegrationTests extends UserRepositoryIntegrationTestsDelegator {
|
||||
|
||||
@Configuration
|
||||
@EnableCassandraRepositories(basePackageClasses = UserRepository.class)
|
||||
@@ -51,42 +43,4 @@ public class UserRepositoryJavaConfigIntegrationTests extends AbstractSpringData
|
||||
}
|
||||
}
|
||||
|
||||
@Autowired
|
||||
protected UserRepository repository;
|
||||
|
||||
@Autowired
|
||||
protected CassandraOperations template;
|
||||
|
||||
UserRepositoryIntegrationTests tests;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
tests = new UserRepositoryIntegrationTests(repository, template);
|
||||
tests.before();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsUserById() throws Exception {
|
||||
tests.findsUserById();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAll() throws Exception {
|
||||
tests.findsAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAllWithGivenIds() {
|
||||
tests.findsAllWithGivenIds();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserCorrectly() throws Exception {
|
||||
tests.deletesUserCorrectly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserByIdCorrectly() {
|
||||
tests.deletesUserByIdCorrectly();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,60 +15,13 @@
|
||||
*/
|
||||
package org.springframework.data.cassandra.test.integration.repository;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.data.cassandra.core.CassandraOperations;
|
||||
import org.springframework.data.cassandra.test.integration.support.AbstractSpringDataEmbeddedCassandraIntegrationTest;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* Base class for xml config tests for {@link UserRepository}.
|
||||
* xml config tests for {@link UserRepository}.
|
||||
*
|
||||
* @author Matthew T. Adams
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration
|
||||
public class UserRepositoryXmlConfigIntegrationTests extends AbstractSpringDataEmbeddedCassandraIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
protected UserRepository repository;
|
||||
|
||||
@Autowired
|
||||
protected CassandraOperations template;
|
||||
|
||||
UserRepositoryIntegrationTests tests;
|
||||
|
||||
@Before
|
||||
public void before() {
|
||||
tests = new UserRepositoryIntegrationTests(repository, template);
|
||||
tests.before();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsUserById() throws Exception {
|
||||
tests.findsUserById();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAll() throws Exception {
|
||||
tests.findsAll();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void findsAllWithGivenIds() {
|
||||
tests.findsAllWithGivenIds();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserCorrectly() throws Exception {
|
||||
tests.deletesUserCorrectly();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void deletesUserByIdCorrectly() {
|
||||
tests.deletesUserByIdCorrectly();
|
||||
}
|
||||
public class UserRepositoryXmlConfigIntegrationTests extends UserRepositoryIntegrationTestsDelegator {
|
||||
}
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
Person.findFolksWithLastnameAsList=select * from person where lastname = '?0'
|
||||
Person.findFolksWithLastnameAsResultSet=select * from person where lastname = '?0'
|
||||
Person.findFolksWithLastnameAsArray=select * from person where lastname = '?0'
|
||||
Person.findSingle=select * from person where lastname = '?0' and firstname = '?1'
|
||||
Person.findFolksWithLastnameAsListOfMapOfStringToObject=select * from person where lastname = '?0'
|
||||
Person.findSingleNickname=select nickname from person where lastname = '?0' and firstname = '?1'
|
||||
Person.findSingleBirthdate=select birthdate from person where lastname = '?0' and firstname = '?1'
|
||||
Person.findSingleCool=select cool from person where lastname = '?0' and firstname = '?1'
|
||||
Person.findSingleNumberOfChildren=select numberofchildren from person where lastname = '?0' and firstname = '?1'
|
||||
@@ -1 +1 @@
|
||||
User.findByNamedQuery=SELECT firstName FROM table WHERE firstName=?0
|
||||
User.findByNamedQuery=SELECT firstname FROM users WHERE username='?0'
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
entity-base-packages="org.springframework.data.cassandra.test.integration.repository">
|
||||
<cass:entity
|
||||
class="org.springframework.data.cassandra.test.integration.repository.User">
|
||||
<cass:table name="users_x" />
|
||||
<cass:table name="users" />
|
||||
</cass:entity>
|
||||
</cass:mapping>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user