Added basic select methods to TemplateAPI
This commit is contained in:
@@ -22,9 +22,11 @@ import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
|
||||
import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* Main Inteface that should be used for Cassandra interactions
|
||||
* Operations for interacting with Cassandra. These operations are used by the Repository implementation, but can also
|
||||
* be used directly when that is desired by the developer.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
* @author David Webb
|
||||
@@ -70,7 +72,7 @@ public interface CassandraOperations {
|
||||
* @param selectClass must not be {@literal null}, mapped entity type.
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> select(String query, Class<T> selectClass);
|
||||
<T> List<T> selectByCQL(String query, Class<T> selectClass);
|
||||
|
||||
/**
|
||||
* Execute query and convert ResultSet to the entity
|
||||
@@ -79,7 +81,11 @@ public interface CassandraOperations {
|
||||
* @param selectClass must not be {@literal null}, mapped entity type.
|
||||
* @return
|
||||
*/
|
||||
<T> T selectOne(String query, Class<T> selectClass);
|
||||
<T> T selectOneByCQL(String query, Class<T> selectClass);
|
||||
|
||||
<T> List<T> select(Select selectQuery, Class<T> selectClass);
|
||||
|
||||
<T> T selectOne(Select selectQuery, Class<T> selectClass);
|
||||
|
||||
/**
|
||||
* Insert the given object to the table by id.
|
||||
|
||||
@@ -32,12 +32,10 @@ import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
import org.springframework.data.cassandra.convert.CassandraConverter;
|
||||
import org.springframework.data.cassandra.core.exceptions.CassandraConnectionFailureException;
|
||||
import org.springframework.data.cassandra.exception.EntityWriterException;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentEntity;
|
||||
import org.springframework.data.cassandra.mapping.CassandraPersistentProperty;
|
||||
import org.springframework.data.cassandra.util.CqlUtils;
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.data.mapping.context.MappingContext;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
@@ -48,8 +46,8 @@ import com.datastax.driver.core.ResultSet;
|
||||
import com.datastax.driver.core.ResultSetFuture;
|
||||
import com.datastax.driver.core.Row;
|
||||
import com.datastax.driver.core.Session;
|
||||
import com.datastax.driver.core.exceptions.NoHostAvailableException;
|
||||
import com.datastax.driver.core.querybuilder.Batch;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* The Cassandra Template is a convenience API for all Cassnadra DML Operations.
|
||||
@@ -59,31 +57,6 @@ import com.datastax.driver.core.querybuilder.Batch;
|
||||
*/
|
||||
public class CassandraTemplate implements CassandraOperations {
|
||||
|
||||
/**
|
||||
* Simple {@link RowCallback} that will transform {@link Row} into the given target type using the given
|
||||
* {@link EntityReader}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
private static class ReadRowCallback<T> implements RowCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, Object> reader;
|
||||
private final Class<T> type;
|
||||
|
||||
public ReadRowCallback(EntityReader<? super T, Object> reader, Class<T> type) {
|
||||
Assert.notNull(reader);
|
||||
Assert.notNull(type);
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T doWith(Row row) {
|
||||
T source = reader.read(type, row);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
|
||||
private static Logger log = LoggerFactory.getLogger(CassandraTemplate.class);
|
||||
public static final Collection<String> ITERABLE_CLASSES;
|
||||
|
||||
@@ -700,20 +673,36 @@ public class CassandraTemplate implements CassandraOperations {
|
||||
return insertAsynchronously(entity, tableName, options.toMap());
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.CassandraOperations#select(com.datastax.driver.core.querybuilder.Select, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> List<T> select(Select selectQuery, Class<T> selectClass) {
|
||||
return selectByCQL(selectQuery.getQueryString(), selectClass);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.CassandraOperations#select(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> List<T> select(String query, Class<T> selectClass) {
|
||||
return selectInternal(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
public <T> List<T> selectByCQL(String query, Class<T> selectClass) {
|
||||
return doSelect(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.CassandraOperations#selectOne(com.datastax.driver.core.querybuilder.Select, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> T selectOne(Select selectQuery, Class<T> selectClass) {
|
||||
return selectOneByCQL(selectQuery.getQueryString(), selectClass);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.cassandra.core.CassandraOperations#selectOne(java.lang.String, java.lang.Class)
|
||||
*/
|
||||
@Override
|
||||
public <T> T selectOne(String query, Class<T> selectClass) {
|
||||
return selectOneInternal(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
public <T> T selectOneByCQL(String query, Class<T> selectClass) {
|
||||
return doSelectOne(query, new ReadRowCallback<T>(cassandraConverter, selectClass));
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -958,6 +947,70 @@ public class CassandraTemplate implements CassandraOperations {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param query
|
||||
* @param readRowCallback
|
||||
* @return
|
||||
*/
|
||||
private <T> List<T> doSelect(final String query, ReadRowCallback<T> readRowCallback) {
|
||||
|
||||
ResultSet resultSet = execute(new SessionCallback<ResultSet>() {
|
||||
|
||||
@Override
|
||||
public ResultSet doInSession(Session s) throws DataAccessException {
|
||||
return s.execute(query);
|
||||
}
|
||||
});
|
||||
|
||||
if (resultSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<T> result = new ArrayList<T>();
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
result.add(readRowCallback.doWith(row));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param query
|
||||
* @param readRowCallback
|
||||
* @return
|
||||
*/
|
||||
private <T> T doSelectOne(final String query, ReadRowCallback<T> readRowCallback) {
|
||||
|
||||
/*
|
||||
* Run the Query
|
||||
*/
|
||||
ResultSet resultSet = execute(new SessionCallback<ResultSet>() {
|
||||
|
||||
@Override
|
||||
public ResultSet doInSession(Session s) throws DataAccessException {
|
||||
return s.execute(query);
|
||||
}
|
||||
});
|
||||
|
||||
if (resultSet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
T result = readRowCallback.doWith(row);
|
||||
if (iterator.hasNext()) {
|
||||
throw new DuplicateKeyException("found two or more results in query " + query);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private RuntimeException potentiallyConvertRuntimeException(RuntimeException ex) {
|
||||
RuntimeException resolved = this.exceptionTranslator.translateExceptionIfPossible(ex);
|
||||
return resolved == null ? ex : resolved;
|
||||
@@ -1240,51 +1293,4 @@ public class CassandraTemplate implements CassandraOperations {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param query
|
||||
* @param readRowCallback
|
||||
* @return
|
||||
*/
|
||||
<T> List<T> selectInternal(String query, ReadRowCallback<T> readRowCallback) {
|
||||
try {
|
||||
ResultSet resultSet = session.execute(query);
|
||||
List<T> result = new ArrayList<T>();
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
result.add(readRowCallback.doWith(row));
|
||||
}
|
||||
return result;
|
||||
} catch (NoHostAvailableException e) {
|
||||
throw new CassandraConnectionFailureException(null, "no host available", e);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param query
|
||||
* @param readRowCallback
|
||||
* @return
|
||||
*/
|
||||
<T> T selectOneInternal(String query, ReadRowCallback<T> readRowCallback) {
|
||||
try {
|
||||
ResultSet resultSet = session.execute(query);
|
||||
Iterator<Row> iterator = resultSet.iterator();
|
||||
if (iterator.hasNext()) {
|
||||
Row row = iterator.next();
|
||||
T result = readRowCallback.doWith(row);
|
||||
if (iterator.hasNext()) {
|
||||
throw new DuplicateKeyException("found two or more results in query " + query);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return null;
|
||||
} catch (NoHostAvailableException e) {
|
||||
throw new CassandraConnectionFailureException(null, "no host available", e);
|
||||
} catch (RuntimeException e) {
|
||||
throw potentiallyConvertRuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,7 +19,7 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Contains Query Options for Cassnadra queries. This controls the Consistency Tuning and Retry Policy for a Query.
|
||||
* Contains Query Options for Cassandra queries. This controls the Consistency Tuning and Retry Policy for a Query.
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* 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.core;
|
||||
|
||||
import org.springframework.data.convert.EntityReader;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.datastax.driver.core.Row;
|
||||
|
||||
/**
|
||||
* Simple {@link RowCallback} that will transform {@link Row} into the given target type using the given
|
||||
* {@link EntityReader}.
|
||||
*
|
||||
* @author Alex Shvid
|
||||
*/
|
||||
public class ReadRowCallback<T> implements RowCallback<T> {
|
||||
|
||||
private final EntityReader<? super T, Object> reader;
|
||||
private final Class<T> type;
|
||||
|
||||
public ReadRowCallback(EntityReader<? super T, Object> reader, Class<T> type) {
|
||||
Assert.notNull(reader);
|
||||
Assert.notNull(type);
|
||||
this.reader = reader;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T doWith(Row row) {
|
||||
T source = reader.read(type, row);
|
||||
return source;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import junit.framework.Assert;
|
||||
|
||||
import org.apache.cassandra.exceptions.ConfigurationException;
|
||||
import org.apache.thrift.transport.TTransportException;
|
||||
import org.cassandraunit.CassandraCQLUnit;
|
||||
@@ -51,8 +53,11 @@ import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.support.AnnotationConfigContextLoader;
|
||||
|
||||
import com.datastax.driver.core.querybuilder.QueryBuilder;
|
||||
import com.datastax.driver.core.querybuilder.Select;
|
||||
|
||||
/**
|
||||
* Unit Tests for CassnadraTemplate
|
||||
* Unit Tests for CassandraTemplate
|
||||
*
|
||||
* @author David Webb
|
||||
*
|
||||
@@ -880,6 +885,33 @@ public class CassandraOperationsTest {
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void selectTest() {
|
||||
|
||||
/*
|
||||
* Test Single Insert with entity
|
||||
*/
|
||||
Book b1 = new Book();
|
||||
b1.setIsbn("123456-1");
|
||||
b1.setTitle("Spring Data Cassandra Guide");
|
||||
b1.setAuthor("Cassandra Guru");
|
||||
b1.setPages(521);
|
||||
|
||||
cassandraTemplate.insert(b1);
|
||||
|
||||
Select select = QueryBuilder.select().all().from("book");
|
||||
select.where(QueryBuilder.eq("isbn", "123456-1"));
|
||||
|
||||
Book b = cassandraTemplate.selectOne(select, Book.class);
|
||||
|
||||
log.info("SingleSelect Book Title -> " + b.getTitle());
|
||||
log.info("SingleSelect Book Author -> " + b.getAuthor());
|
||||
|
||||
Assert.assertEquals(b.getTitle(), "Spring Data Cassandra Guide");
|
||||
Assert.assertEquals(b.getAuthor(), "Cassandra Guru");
|
||||
|
||||
}
|
||||
|
||||
@After
|
||||
public void clearCassandra() {
|
||||
EmbeddedCassandraServerHelper.cleanEmbeddedCassandra();
|
||||
|
||||
Reference in New Issue
Block a user