From c6119ca7fab5f4743f6fd2143b7df824dad55bb3 Mon Sep 17 00:00:00 2001 From: dwebb Date: Fri, 15 Nov 2013 16:57:44 -0500 Subject: [PATCH 1/3] wip: Completed single update and delete tests. --- .../cassandra/core/CassandraOperations.java | 24 +- .../cassandra/core/CassandraTemplate.java | 66 ++--- .../data/cassandra/util/CqlUtils.java | 28 +- .../template/CassandraOperationsTest.java | 277 ++++++++++++++++++ 4 files changed, 336 insertions(+), 59 deletions(-) diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java b/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java index 0b0361dfe..dbb5cb6d1 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java @@ -545,35 +545,35 @@ public interface CassandraOperations { * * @param object */ - void deleteAsychronously(T entity); + void deleteAsynchronously(T entity); /** * @param entity * @param tableName * @param options */ - void deleteAsychronously(T entity, QueryOptions options); + void deleteAsynchronously(T entity, QueryOptions options); /** * @param entity * @param tableName * @param optionsByName */ - void deleteAsychronously(T entity, Map optionsByName); + void deleteAsynchronously(T entity, Map optionsByName); /** * @param entity * @param tableName * @param options */ - void deleteAsychronously(T entity, String tableName, QueryOptions options); + void deleteAsynchronously(T entity, String tableName, QueryOptions options); /** * @param entity * @param tableName * @param optionsByName */ - void deleteAsychronously(T entity, String tableName, Map optionsByName); + void deleteAsynchronously(T entity, String tableName, Map optionsByName); /** * Removes the given object from the given table. @@ -581,14 +581,14 @@ public interface CassandraOperations { * @param object * @param table must not be {@literal null} or empty. */ - void deleteAsychronously(T entity, String tableName); + void deleteAsynchronously(T entity, String tableName); /** * Remove the given object from the table by id. * * @param object */ - void deleteAsychronously(List entities); + void deleteAsynchronously(List entities); /** * Removes the given object from the given table. @@ -596,35 +596,35 @@ public interface CassandraOperations { * @param object * @param table must not be {@literal null} or empty. */ - void deleteAsychronously(List entities, String tableName); + void deleteAsynchronously(List entities, String tableName); /** * @param entities * @param tableName * @param options */ - void deleteAsychronously(List entities, QueryOptions options); + void deleteAsynchronously(List entities, QueryOptions options); /** * @param entities * @param tableName * @param optionsByName */ - void deleteAsychronously(List entities, Map optionsByName); + void deleteAsynchronously(List entities, Map optionsByName); /** * @param entities * @param tableName * @param options */ - void deleteAsychronously(List entities, String tableName, QueryOptions options); + void deleteAsynchronously(List entities, String tableName, QueryOptions options); /** * @param entities * @param tableName * @param optionsByName */ - void deleteAsychronously(List entities, String tableName, Map optionsByName); + void deleteAsynchronously(List entities, String tableName, Map optionsByName); /** * Returns the underlying {@link CassandraConverter}. diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java index c69951073..70d2d0b2b 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java @@ -234,48 +234,48 @@ public class CassandraTemplate implements CassandraOperations { } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List) */ @Override - public void deleteAsychronously(List entities) { + public void deleteAsynchronously(List entities) { String tableName = getTableName(entities.get(0).getClass()); Assert.notNull(tableName); - deleteAsychronously(entities, tableName); + deleteAsynchronously(entities, tableName); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List, java.util.Map) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List, java.util.Map) */ @Override - public void deleteAsychronously(List entities, Map optionsByName) { + public void deleteAsynchronously(List entities, Map optionsByName) { String tableName = getTableName(entities.get(0).getClass()); Assert.notNull(tableName); - deleteAsychronously(entities, tableName, optionsByName); + deleteAsynchronously(entities, tableName, optionsByName); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List, org.springframework.data.cassandra.core.QueryOptions) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List, org.springframework.data.cassandra.core.QueryOptions) */ @Override - public void deleteAsychronously(List entities, QueryOptions options) { + public void deleteAsynchronously(List entities, QueryOptions options) { String tableName = getTableName(entities.get(0).getClass()); Assert.notNull(tableName); - deleteAsychronously(entities, tableName, options); + deleteAsynchronously(entities, tableName, options); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List, java.lang.String) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List, java.lang.String) */ @Override - public void deleteAsychronously(List entities, String tableName) { + public void deleteAsynchronously(List entities, String tableName) { insertAsynchronously(entities, tableName, new HashMap()); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List, java.lang.String, java.util.Map) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List, java.lang.String, java.util.Map) */ @Override - public void deleteAsychronously(List entities, String tableName, Map optionsByName) { + public void deleteAsynchronously(List entities, String tableName, Map optionsByName) { Assert.notNull(entities); Assert.notEmpty(entities); Assert.notNull(tableName); @@ -284,56 +284,56 @@ public class CassandraTemplate implements CassandraOperations { } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.util.List, java.lang.String, org.springframework.data.cassandra.core.QueryOptions) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.util.List, java.lang.String, org.springframework.data.cassandra.core.QueryOptions) */ @Override - public void deleteAsychronously(List entities, String tableName, QueryOptions options) { - deleteAsychronously(entities, tableName, options.toMap()); + public void deleteAsynchronously(List entities, String tableName, QueryOptions options) { + deleteAsynchronously(entities, tableName, options.toMap()); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object) */ @Override - public void deleteAsychronously(T entity) { + public void deleteAsynchronously(T entity) { String tableName = getTableName(entity.getClass()); Assert.notNull(tableName); - deleteAsychronously(entity, tableName); + deleteAsynchronously(entity, tableName); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object, java.util.Map) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object, java.util.Map) */ @Override - public void deleteAsychronously(T entity, Map optionsByName) { + public void deleteAsynchronously(T entity, Map optionsByName) { String tableName = getTableName(entity.getClass()); Assert.notNull(tableName); - deleteAsychronously(entity, tableName, optionsByName); + deleteAsynchronously(entity, tableName, optionsByName); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object, org.springframework.data.cassandra.core.QueryOptions) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object, org.springframework.data.cassandra.core.QueryOptions) */ @Override - public void deleteAsychronously(T entity, QueryOptions options) { + public void deleteAsynchronously(T entity, QueryOptions options) { String tableName = getTableName(entity.getClass()); Assert.notNull(tableName); - deleteAsychronously(entity, tableName, options); + deleteAsynchronously(entity, tableName, options); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object, java.lang.String) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object, java.lang.String) */ @Override - public void deleteAsychronously(T entity, String tableName) { - deleteAsychronously(entity, tableName, new HashMap()); + public void deleteAsynchronously(T entity, String tableName) { + deleteAsynchronously(entity, tableName, new HashMap()); } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object, java.lang.String, java.util.Map) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object, java.lang.String, java.util.Map) */ @Override - public void deleteAsychronously(T entity, String tableName, Map optionsByName) { + public void deleteAsynchronously(T entity, String tableName, Map optionsByName) { Assert.notNull(entity); Assert.notNull(tableName); Assert.notNull(optionsByName); @@ -341,11 +341,11 @@ public class CassandraTemplate implements CassandraOperations { } /* (non-Javadoc) - * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsychronously(java.lang.Object, java.lang.String, org.springframework.data.cassandra.core.QueryOptions) + * @see org.springframework.data.cassandra.core.CassandraOperations#deleteAsynchronously(java.lang.Object, java.lang.String, org.springframework.data.cassandra.core.QueryOptions) */ @Override - public void deleteAsychronously(T entity, String tableName, QueryOptions options) { - deleteAsychronously(entity, tableName, options.toMap()); + public void deleteAsynchronously(T entity, String tableName, QueryOptions options) { + deleteAsynchronously(entity, tableName, options.toMap()); } /* (non-Javadoc) diff --git a/src/main/java/org/springframework/data/cassandra/util/CqlUtils.java b/src/main/java/org/springframework/data/cassandra/util/CqlUtils.java index 90cfe1610..89aee635a 100644 --- a/src/main/java/org/springframework/data/cassandra/util/CqlUtils.java +++ b/src/main/java/org/springframework/data/cassandra/util/CqlUtils.java @@ -31,7 +31,6 @@ import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Update; /** - * * Utilties to convert Cassandra Annotated objects to Queries and CQL. * * @author Alex Shvid @@ -204,11 +203,9 @@ public abstract class CqlUtils { * * @param keyspaceName * @param tableName - * @param entity * @param objectToSave + * @param entity * @param optionsByName - * @param mappingContext - * @param beanClassLoader * * @return The Query object to run with session.execute(); * @throws EntityWriterException @@ -270,11 +267,9 @@ public abstract class CqlUtils { * * @param keyspaceName * @param tableName - * @param entity * @param objectToSave + * @param entity * @param optionsByName - * @param mappingContext - * @param beanClassLoader * * @return The Query object to run with session.execute(); * @throws EntityWriterException @@ -340,10 +335,9 @@ public abstract class CqlUtils { * * @param keyspaceName * @param tableName - * @param entity * @param objectsToSave - * @param mappingContext - * @param beanClassLoader + * @param entity + * @param optionsByName * * @return The Query object to run with session.execute(); * @throws EntityWriterException @@ -374,10 +368,9 @@ public abstract class CqlUtils { * * @param keyspaceName * @param tableName - * @param entity * @param objectsToSave - * @param mappingContext - * @param beanClassLoader + * @param entity + * @param optionsByName * * @return The Query object to run with session.execute(); * @throws EntityWriterException @@ -404,10 +397,13 @@ public abstract class CqlUtils { } /** + * Create a Delete Query Object from an annotated POJO + * * @param keyspace * @param tableName * @param objectToRemove * @param entity + * @param optionsByName * @return * @throws EntityWriterException */ @@ -496,10 +492,14 @@ public abstract class CqlUtils { } /** + * Create a Batch Query object for multiple deletes. + * * @param keyspace * @param tableName * @param entities - * @param cPEntity + * @param entity + * @param optionsByName + * * @return * @throws EntityWriterException */ diff --git a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java index da42d9af8..7e0764012 100644 --- a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java +++ b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java @@ -359,6 +359,283 @@ public class CassandraOperationsTest { return books; } + @Test + public void updateTest() { + + insertTest(); + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + /* + * Test Single Insert with entity + */ + Book b1 = new Book(); + b1.setIsbn("123456-1"); + b1.setTitle("Spring Data Cassandra Book"); + b1.setAuthor("Cassandra Guru"); + b1.setPages(521); + + cassandraTemplate.update(b1); + + Book b2 = new Book(); + b2.setIsbn("123456-2"); + b2.setTitle("Spring Data Cassandra Book"); + b2.setAuthor("Cassandra Guru"); + b2.setPages(521); + + cassandraTemplate.update(b2, "book_alt"); + + /* + * Test Single Insert with entity + */ + Book b3 = new Book(); + b3.setIsbn("123456-3"); + b3.setTitle("Spring Data Cassandra Book"); + b3.setAuthor("Cassandra Guru"); + b3.setPages(265); + + cassandraTemplate.update(b3, "book", options); + + /* + * Test Single Insert with entity + */ + Book b4 = new Book(); + b4.setIsbn("123456-4"); + b4.setTitle("Spring Data Cassandra Book"); + b4.setAuthor("Cassandra Guru"); + b4.setPages(465); + + cassandraTemplate.update(b4, "book", optionsByName); + + /* + * Test Single Insert with entity + */ + Book b5 = new Book(); + b5.setIsbn("123456-5"); + b5.setTitle("Spring Data Cassandra Book"); + b5.setAuthor("Cassandra Guru"); + b5.setPages(265); + + cassandraTemplate.update(b5, options); + + /* + * Test Single Insert with entity + */ + Book b6 = new Book(); + b6.setIsbn("123456-6"); + b6.setTitle("Spring Data Cassandra Book"); + b6.setAuthor("Cassandra Guru"); + b6.setPages(465); + + cassandraTemplate.update(b6, optionsByName); + + } + + @Test + public void updateAsynchronouslyTest() { + + insertTest(); + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + /* + * Test Single Insert with entity + */ + Book b1 = new Book(); + b1.setIsbn("123456-1"); + b1.setTitle("Spring Data Cassandra Book"); + b1.setAuthor("Cassandra Guru"); + b1.setPages(521); + + cassandraTemplate.updateAsynchronously(b1); + + Book b2 = new Book(); + b2.setIsbn("123456-2"); + b2.setTitle("Spring Data Cassandra Book"); + b2.setAuthor("Cassandra Guru"); + b2.setPages(521); + + cassandraTemplate.updateAsynchronously(b2, "book_alt"); + + /* + * Test Single Insert with entity + */ + Book b3 = new Book(); + b3.setIsbn("123456-3"); + b3.setTitle("Spring Data Cassandra Book"); + b3.setAuthor("Cassandra Guru"); + b3.setPages(265); + + cassandraTemplate.updateAsynchronously(b3, "book", options); + + /* + * Test Single Insert with entity + */ + Book b4 = new Book(); + b4.setIsbn("123456-4"); + b4.setTitle("Spring Data Cassandra Book"); + b4.setAuthor("Cassandra Guru"); + b4.setPages(465); + + cassandraTemplate.updateAsynchronously(b4, "book", optionsByName); + + /* + * Test Single Insert with entity + */ + Book b5 = new Book(); + b5.setIsbn("123456-5"); + b5.setTitle("Spring Data Cassandra Book"); + b5.setAuthor("Cassandra Guru"); + b5.setPages(265); + + cassandraTemplate.updateAsynchronously(b5, options); + + /* + * Test Single Insert with entity + */ + Book b6 = new Book(); + b6.setIsbn("123456-6"); + b6.setTitle("Spring Data Cassandra Book"); + b6.setAuthor("Cassandra Guru"); + b6.setPages(465); + + cassandraTemplate.updateAsynchronously(b6, optionsByName); + + } + + @Test + public void deleteTest() { + + insertTest(); + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + + /* + * Test Single Insert with entity + */ + Book b1 = new Book(); + b1.setIsbn("123456-1"); + + cassandraTemplate.delete(b1); + + Book b2 = new Book(); + b2.setIsbn("123456-2"); + + cassandraTemplate.delete(b2, "book_alt"); + + /* + * Test Single Insert with entity + */ + Book b3 = new Book(); + b3.setIsbn("123456-3"); + + cassandraTemplate.delete(b3, "book", options); + + /* + * Test Single Insert with entity + */ + Book b4 = new Book(); + b4.setIsbn("123456-4"); + + cassandraTemplate.delete(b4, "book", optionsByName); + + /* + * Test Single Insert with entity + */ + Book b5 = new Book(); + b5.setIsbn("123456-5"); + + cassandraTemplate.delete(b5, options); + + /* + * Test Single Insert with entity + */ + Book b6 = new Book(); + b6.setIsbn("123456-6"); + + cassandraTemplate.delete(b6, optionsByName); + + } + + @Test + public void deleteAsynchronouslyTest() { + + insertTest(); + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + + /* + * Test Single Insert with entity + */ + Book b1 = new Book(); + b1.setIsbn("123456-1"); + + cassandraTemplate.deleteAsynchronously(b1); + + Book b2 = new Book(); + b2.setIsbn("123456-2"); + + cassandraTemplate.deleteAsynchronously(b2, "book_alt"); + + /* + * Test Single Insert with entity + */ + Book b3 = new Book(); + b3.setIsbn("123456-3"); + + cassandraTemplate.deleteAsynchronously(b3, "book", options); + + /* + * Test Single Insert with entity + */ + Book b4 = new Book(); + b4.setIsbn("123456-4"); + + cassandraTemplate.deleteAsynchronously(b4, "book", optionsByName); + + /* + * Test Single Insert with entity + */ + Book b5 = new Book(); + b5.setIsbn("123456-5"); + + cassandraTemplate.deleteAsynchronously(b5, options); + + /* + * Test Single Insert with entity + */ + Book b6 = new Book(); + b6.setIsbn("123456-6"); + + cassandraTemplate.deleteAsynchronously(b6, optionsByName); + } + @After public void clearCassandra() { EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); From 5560695c76c7b818f255cf3474626695c05c9dc8 Mon Sep 17 00:00:00 2001 From: dwebb Date: Sun, 17 Nov 2013 00:01:08 -0500 Subject: [PATCH 2/3] wip: Completed updateBatch and deleteBatch tests. --- .../template/CassandraOperationsTest.java | 244 ++++++++++++++++++ 1 file changed, 244 insertions(+) diff --git a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java index 7e0764012..433b89825 100644 --- a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java +++ b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java @@ -517,6 +517,146 @@ public class CassandraOperationsTest { } + @Test + public void updateBatchTest() { + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + List books = null; + + books = getBookList(20); + + cassandraTemplate.insert(books); + + alterBooks(books); + + cassandraTemplate.update(books); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book_alt"); + + alterBooks(books); + + cassandraTemplate.update(books, "book_alt"); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", options); + + alterBooks(books); + + cassandraTemplate.update(books, "book", options); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", optionsByName); + + alterBooks(books); + + cassandraTemplate.update(books, "book", optionsByName); + + books = getBookList(20); + + cassandraTemplate.insert(books, options); + + alterBooks(books); + + cassandraTemplate.update(books, options); + + books = getBookList(20); + + cassandraTemplate.insert(books, optionsByName); + + alterBooks(books); + + cassandraTemplate.update(books, optionsByName); + + } + + @Test + public void updateBatchAsynchronouslyTest() { + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + List books = null; + + books = getBookList(20); + + cassandraTemplate.insert(books); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book_alt"); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books, "book_alt"); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", options); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books, "book", options); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", optionsByName); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books, "book", optionsByName); + + books = getBookList(20); + + cassandraTemplate.insert(books, options); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books, options); + + books = getBookList(20); + + cassandraTemplate.insert(books, optionsByName); + + alterBooks(books); + + cassandraTemplate.updateAsynchronously(books, optionsByName); + + } + + /** + * @param books + */ + private void alterBooks(List books) { + + for (Book b : books) { + b.setAuthor("Ernest Hemmingway"); + b.setTitle("The Old Man and the Sea"); + b.setPages(115); + } + } + @Test public void deleteTest() { @@ -636,6 +776,110 @@ public class CassandraOperationsTest { cassandraTemplate.deleteAsynchronously(b6, optionsByName); } + @Test + public void deleteBatchTest() { + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + List books = null; + + books = getBookList(20); + + cassandraTemplate.insert(books); + + cassandraTemplate.delete(books); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book_alt"); + + cassandraTemplate.delete(books, "book_alt"); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", options); + + cassandraTemplate.delete(books, "book", options); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", optionsByName); + + cassandraTemplate.delete(books, "book", optionsByName); + + books = getBookList(20); + + cassandraTemplate.insert(books, options); + + cassandraTemplate.delete(books, options); + + books = getBookList(20); + + cassandraTemplate.insert(books, optionsByName); + + cassandraTemplate.delete(books, optionsByName); + + } + + @Test + public void deleteBatchAsynchronouslyTest() { + + QueryOptions options = new QueryOptions(); + options.setConsistencyLevel(ConsistencyLevel.ONE); + options.setRetryPolicy(RetryPolicy.DOWNGRADING_CONSISTENCY); + + Map optionsByName = new HashMap(); + optionsByName.put(QueryOptions.QueryOptionMapKeys.CONSISTENCY_LEVEL, ConsistencyLevel.ALL); + optionsByName.put(QueryOptions.QueryOptionMapKeys.RETRY_POLICY, RetryPolicy.FALLTHROUGH); + optionsByName.put(QueryOptions.QueryOptionMapKeys.TTL, 30); + + List books = null; + + books = getBookList(20); + + cassandraTemplate.insert(books); + + cassandraTemplate.deleteAsynchronously(books); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book_alt"); + + cassandraTemplate.deleteAsynchronously(books, "book_alt"); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", options); + + cassandraTemplate.deleteAsynchronously(books, "book", options); + + books = getBookList(20); + + cassandraTemplate.insert(books, "book", optionsByName); + + cassandraTemplate.deleteAsynchronously(books, "book", optionsByName); + + books = getBookList(20); + + cassandraTemplate.insert(books, options); + + cassandraTemplate.deleteAsynchronously(books, options); + + books = getBookList(20); + + cassandraTemplate.insert(books, optionsByName); + + cassandraTemplate.deleteAsynchronously(books, optionsByName); + + } + @After public void clearCassandra() { EmbeddedCassandraServerHelper.cleanEmbeddedCassandra(); From 3ff3e169de8c430c32969d5fb48a368666384779 Mon Sep 17 00:00:00 2001 From: dwebb Date: Mon, 18 Nov 2013 16:00:38 -0500 Subject: [PATCH 3/3] Added basic select methods to TemplateAPI --- .../cassandra/core/CassandraOperations.java | 12 +- .../cassandra/core/CassandraTemplate.java | 164 +++++++++--------- .../data/cassandra/core/QueryOptions.java | 2 +- .../data/cassandra/core/ReadRowCallback.java | 46 +++++ .../template/CassandraOperationsTest.java | 34 +++- 5 files changed, 174 insertions(+), 84 deletions(-) create mode 100644 src/main/java/org/springframework/data/cassandra/core/ReadRowCallback.java diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java b/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java index dbb5cb6d1..98f512fd3 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java @@ -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 */ - List select(String query, Class selectClass); + List selectByCQL(String query, Class 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 selectOne(String query, Class selectClass); + T selectOneByCQL(String query, Class selectClass); + + List select(Select selectQuery, Class selectClass); + + T selectOne(Select selectQuery, Class selectClass); /** * Insert the given object to the table by id. diff --git a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java index b9ff28832..598730268 100644 --- a/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java +++ b/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java @@ -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 implements RowCallback { - - private final EntityReader reader; - private final Class type; - - public ReadRowCallback(EntityReader reader, Class 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 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 List select(Select selectQuery, Class selectClass) { + return selectByCQL(selectQuery.getQueryString(), selectClass); + } + /* (non-Javadoc) * @see org.springframework.data.cassandra.core.CassandraOperations#select(java.lang.String, java.lang.Class) */ @Override - public List select(String query, Class selectClass) { - return selectInternal(query, new ReadRowCallback(cassandraConverter, selectClass)); + public List selectByCQL(String query, Class selectClass) { + return doSelect(query, new ReadRowCallback(cassandraConverter, selectClass)); + } + + /* (non-Javadoc) + * @see org.springframework.data.cassandra.core.CassandraOperations#selectOne(com.datastax.driver.core.querybuilder.Select, java.lang.Class) + */ + @Override + public T selectOne(Select selectQuery, Class 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 selectOne(String query, Class selectClass) { - return selectOneInternal(query, new ReadRowCallback(cassandraConverter, selectClass)); + public T selectOneByCQL(String query, Class selectClass) { + return doSelectOne(query, new ReadRowCallback(cassandraConverter, selectClass)); } /* (non-Javadoc) @@ -958,6 +947,70 @@ public class CassandraTemplate implements CassandraOperations { return null; } + /** + * @param query + * @param readRowCallback + * @return + */ + private List doSelect(final String query, ReadRowCallback readRowCallback) { + + ResultSet resultSet = execute(new SessionCallback() { + + @Override + public ResultSet doInSession(Session s) throws DataAccessException { + return s.execute(query); + } + }); + + if (resultSet == null) { + return null; + } + + List result = new ArrayList(); + Iterator iterator = resultSet.iterator(); + while (iterator.hasNext()) { + Row row = iterator.next(); + result.add(readRowCallback.doWith(row)); + } + + return result; + } + + /** + * @param query + * @param readRowCallback + * @return + */ + private T doSelectOne(final String query, ReadRowCallback readRowCallback) { + + /* + * Run the Query + */ + ResultSet resultSet = execute(new SessionCallback() { + + @Override + public ResultSet doInSession(Session s) throws DataAccessException { + return s.execute(query); + } + }); + + if (resultSet == null) { + return null; + } + + Iterator 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 - */ - List selectInternal(String query, ReadRowCallback readRowCallback) { - try { - ResultSet resultSet = session.execute(query); - List result = new ArrayList(); - Iterator 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 selectOneInternal(String query, ReadRowCallback readRowCallback) { - try { - ResultSet resultSet = session.execute(query); - Iterator 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); - } - } - } diff --git a/src/main/java/org/springframework/data/cassandra/core/QueryOptions.java b/src/main/java/org/springframework/data/cassandra/core/QueryOptions.java index 86ea87a6b..5d3755dfb 100644 --- a/src/main/java/org/springframework/data/cassandra/core/QueryOptions.java +++ b/src/main/java/org/springframework/data/cassandra/core/QueryOptions.java @@ -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 * diff --git a/src/main/java/org/springframework/data/cassandra/core/ReadRowCallback.java b/src/main/java/org/springframework/data/cassandra/core/ReadRowCallback.java new file mode 100644 index 000000000..bccc4ded7 --- /dev/null +++ b/src/main/java/org/springframework/data/cassandra/core/ReadRowCallback.java @@ -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 implements RowCallback { + + private final EntityReader reader; + private final Class type; + + public ReadRowCallback(EntityReader reader, Class 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; + } +} \ No newline at end of file diff --git a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java index 433b89825..7235c9334 100644 --- a/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java +++ b/src/test/java/org/springframework/data/cassandra/template/CassandraOperationsTest.java @@ -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();