DATACASS-569 - Apply UpdateOptions.ifExists through CassandraTemplate.update(…).

We now consider the ifExists option for UPDATE statements when updating an entity using CassandraTemplate.update(…).
This commit is contained in:
Mark Paluch
2018-06-14 13:40:19 +02:00
parent 9474b3de91
commit 34903b7350
4 changed files with 108 additions and 23 deletions

View File

@@ -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.
* <p>
* 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<String, Object> toInsert = new LinkedHashMap<>();
entityWriter.write(objectToUpdate, toInsert, entity);
entityWriter.write(objectToInsert, toInsert, entity);
for (Entry<String, Object> 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;
}
}

View File

@@ -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);
}

View File

@@ -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;");
}
}

View File

@@ -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() {