diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java index f84332881..fba88ab65 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/QueryUtils.java @@ -50,7 +50,7 @@ import com.datastax.driver.core.querybuilder.Select; import com.datastax.driver.core.querybuilder.Update; /** - * Simple utility class for working with the QueryBuilder API. + * Simple utility class for working with the QueryBuilder API using mapped entities. *

* Only intended for internal use. * @@ -66,31 +66,27 @@ class QueryUtils { * Creates a Query Object for an insert. * * @param tableName the table name, must not be empty and not {@literal null}. - * @param objectToUpdate the object to save, must not be {@literal null}. + * @param objectToInsert the object to save, must not be {@literal null}. * @param options optional {@link WriteOptions} to apply to the {@link Insert} statement, may be {@literal null}. * @param entityWriter the {@link EntityWriter} to write insert values. * @param entity must not be {@literal null}. * @return The Query object to run with session.execute(); */ - static Insert createInsertQuery(String tableName, Object objectToUpdate, WriteOptions options, + static Insert createInsertQuery(String tableName, Object objectToInsert, WriteOptions options, CassandraConverter entityWriter, CassandraPersistentEntity entity) { Assert.hasText(tableName, "TableName must not be empty"); - Assert.notNull(objectToUpdate, "Object to insert must not be null"); + Assert.notNull(objectToInsert, "Object to insert must not be null"); Assert.notNull(entityWriter, "CassandraConverter must not be null"); Assert.notNull(entity, "CassandraPersistentEntity must not be null"); - Insert insert = QueryOptionsUtil.addWriteOptions(QueryBuilder.insertInto(tableName), options); + Insert insert = addWriteOptions(QueryBuilder.insertInto(tableName), options); boolean insertNulls = false; if (options instanceof InsertOptions) { InsertOptions insertOptions = (InsertOptions) options; - if (insertOptions.isIfNotExists()) { - insert = insert.ifNotExists(); - } - insertNulls = insertOptions.isInsertNulls(); } @@ -98,13 +94,13 @@ class QueryUtils { Map toInsert = new LinkedHashMap<>(); - entityWriter.write(objectToUpdate, toInsert, entity); + entityWriter.write(objectToInsert, toInsert, entity); for (Entry entry : toInsert.entrySet()) { insert.value(entry.getKey(), entry.getValue()); } } else { - entityWriter.write(objectToUpdate, insert); + entityWriter.write(objectToInsert, insert); } return insert; @@ -127,16 +123,7 @@ class QueryUtils { Assert.notNull(objectToUpdate, "Object to update must not be null"); Assert.notNull(entityWriter, "EntityWriter must not be null"); - Update update = QueryOptionsUtil.addWriteOptions(QueryBuilder.update(tableName), options); - - if (options instanceof UpdateOptions) { - - UpdateOptions updateOptions = (UpdateOptions) options; - - if (updateOptions.isIfExists()) { - update.where().ifExists(); - } - } + Update update = addWriteOptions(QueryBuilder.update(tableName), options); entityWriter.write(objectToUpdate, update); @@ -245,4 +232,75 @@ class QueryUtils { return CqlIdentifier.of("unknown"); } + + /** + * Add common {@link WriteOptions} options to {@link Insert} CQL statements. + * + * @param insert {@link Insert} CQL statement, must not be {@literal null}. + * @param writeOptions write options (e.g. consistency level) to add to the CQL statement. + * @return the given {@link Insert}. + * @see #addWriteOptions(Insert, WriteOptions) + * @since 2.1 + */ + static Insert addWriteOptions(Insert insert, WriteOptions writeOptions) { + + Assert.notNull(insert, "Insert must not be null"); + + if (writeOptions instanceof InsertOptions) { + + InsertOptions insertOptions = (InsertOptions) writeOptions; + + if (insertOptions.isIfNotExists()) { + insert = insert.ifNotExists(); + } + } + + QueryOptionsUtil.addWriteOptions(insert, writeOptions); + + return insert; + } + + /** + * Add common {@link WriteOptions} options to {@link Update} CQL statements. + * + * @param update {@link Update} CQL statement, must not be {@literal null}. + * @param writeOptions write options (e.g. consistency level) to add to the CQL statement. + * @return the given {@link Update}. + * @see QueryOptionsUtil#addWriteOptions(Update, WriteOptions) + * @since 2.1 + */ + static Update addWriteOptions(Update update, WriteOptions writeOptions) { + + Assert.notNull(update, "Update must not be null"); + + QueryOptionsUtil.addWriteOptions(update, writeOptions); + + if (writeOptions instanceof UpdateOptions) { + + UpdateOptions updateOptions = (UpdateOptions) writeOptions; + + if (updateOptions.isIfExists()) { + update.where().ifExists(); + } + } + + return update; + } + + /** + * Add common {@link WriteOptions} options to {@link Delete} CQL statements. + * + * @param delete {@link Delete} CQL statement, must not be {@literal null}. + * @param writeOptions write options (e.g. consistency level) to add to the CQL statement. + * @return the given {@link Delete}. + * @since 2.1 + */ + static Delete addWriteOptions(Delete delete, WriteOptions writeOptions) { + + Assert.notNull(delete, "Delete must not be null"); + + QueryOptionsUtil.addQueryOptions(delete, writeOptions); + + return delete; + } } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java index 35cfc3c19..cfb006c8f 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/StatementFactory.java @@ -313,7 +313,7 @@ public class StatementFactory { query.getQueryOptions().ifPresent(queryOptions -> { if (queryOptions instanceof WriteOptions) { - QueryOptionsUtil.addWriteOptions(update, (WriteOptions) queryOptions); + QueryUtils.addWriteOptions(update, (WriteOptions) queryOptions); } else { QueryOptionsUtil.addQueryOptions(update, queryOptions); } @@ -454,7 +454,7 @@ public class StatementFactory { query.getQueryOptions().ifPresent(queryOptions -> { if (queryOptions instanceof WriteOptions) { - QueryOptionsUtil.addWriteOptions(delete, (WriteOptions) queryOptions); + QueryUtils.addWriteOptions(delete, (WriteOptions) queryOptions); } else { QueryOptionsUtil.addQueryOptions(delete, queryOptions); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/QueryUtilsUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/QueryUtilsUnitTests.java index dee39a2d3..05d506608 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/QueryUtilsUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/QueryUtilsUnitTests.java @@ -18,9 +18,12 @@ package org.springframework.data.cassandra.core; import static org.assertj.core.api.Assertions.*; import org.junit.Test; +import org.springframework.data.cassandra.core.convert.MappingCassandraConverter; import org.springframework.data.cassandra.core.cql.CqlIdentifier; +import org.springframework.data.cassandra.domain.User; import com.datastax.driver.core.SimpleStatement; +import com.datastax.driver.core.querybuilder.Insert; import com.datastax.driver.core.querybuilder.QueryBuilder; import com.datastax.driver.core.querybuilder.Select; @@ -31,6 +34,8 @@ import com.datastax.driver.core.querybuilder.Select; */ public class QueryUtilsUnitTests { + private final MappingCassandraConverter converter = new MappingCassandraConverter(); + @Test // DATACASS-106 public void shouldRetrieveTableNameFromSelect() { @@ -57,4 +62,15 @@ public class QueryUtilsUnitTests { assertThat(tableName).isEqualTo(CqlIdentifier.of("table")); } + + @Test // DATACASS-569 + public void shouldCreateInsertQuery() { + + User user = new User("heisenberg", "Walter", "White"); + Insert insert = QueryUtils.createInsertQuery("user", user, InsertOptions.builder().withIfNotExists().build(), + converter, converter.getMappingContext().getRequiredPersistentEntity(User.class)); + + assertThat(insert.toString()) + .isEqualTo("INSERT INTO user (firstname,id,lastname) VALUES ('Walter','heisenberg','White') IF NOT EXISTS;"); + } } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/StatementFactoryUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/StatementFactoryUnitTests.java index e95eaa7c5..e668d0a87 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/StatementFactoryUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/StatementFactoryUnitTests.java @@ -249,6 +249,17 @@ public class StatementFactoryUnitTests { assertThat(update.toString()).isEqualTo("UPDATE person SET number=number-1;"); } + @Test // DATACASS-569 + public void shouldCreateSetUpdateIfExists() { + + Query query = Query.query(Criteria.where("foo").is("bar")) + .queryOptions(UpdateOptions.builder().withIfExists().build()); + + Statement update = statementFactory.update(query, Update.empty().set("firstName", "baz"), personEntity); + + assertThat(update.toString()).isEqualTo("UPDATE person SET first_name='baz' WHERE foo='bar' IF EXISTS;"); + } + @Test // DATACASS-512 public void shouldCreateCountQuery() {