From 0ccb64a686445f93cc40be403e65e67e1eb2f2a2 Mon Sep 17 00:00:00 2001 From: Mark Paluch Date: Wed, 5 Jul 2017 12:51:37 +0200 Subject: [PATCH] =?UTF-8?q?DATACASS-466=20-=20Align=20insert(=E2=80=A6)=20?= =?UTF-8?q?and=20update(=E2=80=A6)=20return=20types=20to=20their=20possibl?= =?UTF-8?q?e=20outcomes.?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We now return WriteResult for insert(…) and update(…) methods accepting WriteOptions. Conditional writes return a state whether the operation was applied or not and this result is propagated via WriteResult to the caller. Synchronous insert(…) and update(…) without WriteOptions methods do not return a value and are consistent with other Template API modules. The absence of an Exception indicates success. Asynchronous and reactive insert(…) and update(…) without WriteOptions continue to return the entity to make the entity accessible after operation completion. Previously, we returned null if a lightweight transaction was not applied or suppressed the value value emission. --- .../core/AsyncCassandraOperations.java | 14 ++- .../core/AsyncCassandraTemplate.java | 23 +++-- .../core/CassandraBatchOperations.java | 3 +- .../core/CassandraBatchTemplate.java | 7 +- .../cassandra/core/CassandraOperations.java | 21 ++-- .../cassandra/core/CassandraTemplate.java | 42 ++++---- .../core/ReactiveCassandraOperations.java | 15 ++- .../core/ReactiveCassandraTemplate.java | 84 +++++++--------- .../data/cassandra/core/WriteResult.java | 97 +++++++++++++++++++ .../support/SimpleCassandraRepository.java | 12 +-- ...syncCassandraTemplateIntegrationTests.java | 16 +-- .../core/AsyncCassandraTemplateUnitTests.java | 36 ------- ...assandraBatchTemplateIntegrationTests.java | 12 ++- .../CassandraTemplateIntegrationTests.java | 25 +++-- .../core/CassandraTemplateUnitTests.java | 44 ++------- ...tiveCassandraTemplateIntegrationTests.java | 13 ++- .../ReactiveCassandraTemplateUnitTests.java | 33 +------ ...ateMapIdProxyDelegateIntegrationTests.java | 34 +++---- ...CassandraTemplateMapIdIntegrationTest.java | 47 ++------- src/main/asciidoc/reference/cassandra.adoc | 8 +- 20 files changed, 264 insertions(+), 322 deletions(-) create mode 100644 spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/WriteResult.java diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraOperations.java index a0a6054d9..0dadd1f7a 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraOperations.java @@ -237,11 +237,10 @@ public interface AsyncCassandraOperations { * * @param entity The entity to insert, must not be {@literal null}. * @param options may be {@literal null}. - * @return the inserted entity or a {@literal null} inside of {@link ListenableFuture} if the {@code INSERT} operation - * was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - ListenableFuture insert(T entity, InsertOptions options) throws DataAccessException; + ListenableFuture insert(Object entity, InsertOptions options) throws DataAccessException; /** * Update the given entity and return the entity if the update was applied. @@ -257,11 +256,10 @@ public interface AsyncCassandraOperations { * * @param entity The entity to update, must not be {@literal null}. * @param options may be {@literal null}. - * @return the updated entity or a {@literal null} inside of {@link ListenableFuture} - * if the {@code UPDATE} operation was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - ListenableFuture update(T entity, UpdateOptions options) throws DataAccessException; + ListenableFuture update(Object entity, UpdateOptions options) throws DataAccessException; /** * Delete the given entity and return the entity if the delete was applied. @@ -277,10 +275,10 @@ public interface AsyncCassandraOperations { * * @param entity must not be {@literal null}. * @param options may be {@literal null}. - * @return the deleted entity. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - ListenableFuture delete(T entity, QueryOptions options) throws DataAccessException; + ListenableFuture delete(Object entity, QueryOptions options) throws DataAccessException; /** * Remove the given object from the table by id. diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraTemplate.java index e2596998d..9d1f86e13 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraTemplate.java @@ -195,7 +195,6 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { return this.statementFactory; } - /* (non-Javadoc) */ private CqlIdentifier getTableName(Object entity) { return getMappingContext().getRequiredPersistentEntity(ClassUtils.getUserClass(entity)).getTableName(); } @@ -418,7 +417,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { */ @Override public ListenableFuture insert(T entity) { - return insert(entity, null); + return new MappingListenableFutureAdapter<>(insert(entity, null), writeResult -> entity); } /* @@ -426,14 +425,14 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { * @see org.springframework.data.cassandra.core.AsyncCassandraOperations#insert(java.lang.Object, org.springframework.data.cassandra.core.InsertOptions) */ @Override - public ListenableFuture insert(T entity, InsertOptions options) { + public ListenableFuture insert(Object entity, InsertOptions options) { Assert.notNull(entity, "Entity must not be null"); Insert insert = QueryUtils.createInsertQuery(getTableName(entity).toCql(), entity, options, getConverter()); return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(insert)), - resultSet -> resultSet.wasApplied() ? entity : null); + WriteResult::of); } /* @@ -442,7 +441,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { */ @Override public ListenableFuture update(T entity) { - return update(entity, null); + return new MappingListenableFutureAdapter<>(update(entity, null), writeResult -> entity); } /* @@ -450,14 +449,14 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { * @see org.springframework.data.cassandra.core.AsyncCassandraOperations#update(java.lang.Object, org.springframework.data.cassandra.core.UpdateOptions) */ @Override - public ListenableFuture update(T entity, UpdateOptions options) { + public ListenableFuture update(Object entity, UpdateOptions options) { Assert.notNull(entity, "Entity must not be null"); Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, getConverter()); return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(update)), - resultSet -> resultSet.wasApplied() ? entity : null); + WriteResult::of); } /* @@ -466,7 +465,7 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { */ @Override public ListenableFuture delete(T entity) { - return delete(entity, null); + return new MappingListenableFutureAdapter<>(delete(entity, null), writeResult -> entity); } /* @@ -474,14 +473,14 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { * @see org.springframework.data.cassandra.core.AsyncCassandraOperations#delete(java.lang.Object, org.springframework.data.cql.core.QueryOptions) */ @Override - public ListenableFuture delete(T entity, QueryOptions options) { + public ListenableFuture delete(Object entity, QueryOptions options) { Assert.notNull(entity, "Entity must not be null"); Delete delete = QueryUtils.createDeleteQuery(getTableName(entity).toCql(), entity, options, getConverter()); return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(new AsyncStatementCallback(delete)), - resultSet -> resultSet.wasApplied() ? entity : null); + WriteResult::of); } /* @@ -518,12 +517,12 @@ public class AsyncCassandraTemplate implements AsyncCassandraOperations { return new MappingListenableFutureAdapter<>(getAsyncCqlOperations().execute(truncate), aBoolean -> null); } - private static class MappingListenableFutureAdapter + static class MappingListenableFutureAdapter extends org.springframework.util.concurrent.ListenableFutureAdapter { private final Function mapper; - public MappingListenableFutureAdapter(ListenableFuture adaptee, Function mapper) { + MappingListenableFutureAdapter(ListenableFuture adaptee, Function mapper) { super(adaptee); this.mapper = mapper; } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchOperations.java index ea1d8d071..b53ea13f2 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchOperations.java @@ -40,9 +40,10 @@ public interface CassandraBatchOperations { /** * Execute the batch. The batch can be executed only once. * + * @return the {@link WriteResult} for the bulk operation. * @throws IllegalStateException if the batch is executed after it was executed already. */ - void execute(); + WriteResult execute(); /** * Apply a given {@code timestamp} to the whole batch. diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchTemplate.java index 393113d76..f87fa9675 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraBatchTemplate.java @@ -59,14 +59,15 @@ class CassandraBatchTemplate implements CassandraBatchOperations { * @see org.springframework.data.cassandra.core.CassandraBatchOperations#execute() */ @Override - public void execute() { + public WriteResult execute() { if (executed.compareAndSet(false, true)) { - operations.getCqlOperations().execute(batch); - return; + return WriteResult.of(operations.getCqlOperations().queryForResultSet(batch)); } assertNotExecuted(); + + return null; // code won't reach this line } /* (non-Javadoc) diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java index 07b9e4dbb..2047cab34 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraOperations.java @@ -258,58 +258,55 @@ public interface CassandraOperations { * Insert the given entity and return the entity if the insert was applied. * * @param entity The entity to insert, must not be {@literal null}. - * @return the inserted entity. * @throws DataAccessException if there is any problem executing the query. */ - T insert(T entity) throws DataAccessException; + void insert(Object entity) throws DataAccessException; /** * Insert the given entity applying {@link WriteOptions} and return the entity if the insert was applied. * * @param entity The entity to insert, must not be {@literal null}. * @param options may be {@literal null}. - * @return the inserted entity or {@literal null} if the {@code INSERT} operation was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - T insert(T entity, InsertOptions options) throws DataAccessException; + WriteResult insert(Object entity, InsertOptions options) throws DataAccessException; /** * Update the given entity and return the entity if the update was applied. * * @param entity The entity to update, must not be {@literal null}. - * @return the updated entity. * @throws DataAccessException if there is any problem executing the query. */ - T update(T entity) throws DataAccessException; + void update(Object entity) throws DataAccessException; /** * Update the given entity applying {@link WriteOptions} and return the entity if the update was applied. * * @param entity The entity to update, must not be {@literal null}. * @param options may be {@literal null}. - * @return the updated entity or {@literal null} if the {@code UPDATE} operation was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - T update(T entity, UpdateOptions options) throws DataAccessException; + WriteResult update(Object entity, UpdateOptions options) throws DataAccessException; /** * Delete the given entity and return the entity if the delete was applied. * * @param entity must not be {@literal null}. - * @return the deleted entity. * @throws DataAccessException if there is any problem executing the query. */ - T delete(T entity) throws DataAccessException; + void delete(Object entity) throws DataAccessException; /** * Delete the given entity applying {@link QueryOptions} and return the entity if the delete was applied. * * @param entity must not be {@literal null}. * @param options may be {@literal null}. - * @return the deleted entity. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem executing the query. */ - T delete(T entity, QueryOptions options) throws DataAccessException; + WriteResult delete(Object entity, QueryOptions options) throws DataAccessException; /** * Remove the given object from the table by id. diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java index f0368cd22..27342ddaf 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java @@ -15,6 +15,9 @@ */ package org.springframework.data.cassandra.core; +import lombok.NonNull; +import lombok.Value; + import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -425,8 +428,8 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#insert(java.lang.Object) */ @Override - public T insert(T entity) { - return insert(entity, null); + public void insert(Object entity) { + insert(entity, null); } /* @@ -434,13 +437,13 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#insert(java.lang.Object, org.springframework.data.cassandra.core.InsertOptions) */ @Override - public T insert(T entity, InsertOptions options) { + public WriteResult insert(Object entity, InsertOptions options) { Assert.notNull(entity, "Entity must not be null"); Insert insert = QueryUtils.createInsertQuery(getTableName(entity.getClass()).toCql(), entity, options, converter); - return getCqlOperations().execute(new StatementCallback<>(insert, entity)); + return getCqlOperations().execute(new StatementCallback(insert)); } /* @@ -448,8 +451,8 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#update(java.lang.Object) */ @Override - public T update(T entity) { - return update(entity, null); + public void update(Object entity) { + update(entity, null); } /* @@ -457,13 +460,13 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#update(java.lang.Object, org.springframework.data.cassandra.core.UpdateOptions) */ @Override - public T update(T entity, UpdateOptions options) { + public WriteResult update(Object entity, UpdateOptions options) { Assert.notNull(entity, "Entity must not be null"); Update update = QueryUtils.createUpdateQuery(getTableName(entity.getClass()).toCql(), entity, options, converter); - return getCqlOperations().execute(new StatementCallback<>(update, entity)); + return getCqlOperations().execute(new StatementCallback(update)); } /* @@ -471,8 +474,8 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#delete(java.lang.Object) */ @Override - public T delete(T entity) { - return delete(entity, null); + public void delete(Object entity) { + delete(entity, null); } /* @@ -480,13 +483,13 @@ public class CassandraTemplate implements CassandraOperations { * @see org.springframework.data.cassandra.core.CassandraOperations#delete(java.lang.Object, org.springframework.data.cql.core.QueryOptions) */ @Override - public T delete(T entity, QueryOptions options) { + public WriteResult delete(Object entity, QueryOptions options) { Assert.notNull(entity, "Entity must not be null"); Delete delete = QueryUtils.createDeleteQuery(getTableName(entity.getClass()).toCql(), entity, options, converter); - return getCqlOperations().execute(new StatementCallback<>(delete, entity)); + return getCqlOperations().execute(new StatementCallback(delete)); } /* @@ -559,19 +562,14 @@ public class CassandraTemplate implements CassandraOperations { return StreamSupport.stream(iterable.spliterator(), false).collect(Collectors.toList()); } - private static class StatementCallback implements SessionCallback, CqlProvider { + @Value + static class StatementCallback implements SessionCallback, CqlProvider { - private final Statement statement; - private final T entity; - - StatementCallback(Statement statement, T entity) { - this.statement = statement; - this.entity = entity; - } + @NonNull Statement statement; @Override - public T doInSession(Session session) throws DriverException, DataAccessException { - return session.execute(statement).wasApplied() ? entity : null; + public WriteResult doInSession(Session session) throws DriverException, DataAccessException { + return WriteResult.of(session.execute(statement)); } @Override diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraOperations.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraOperations.java index ab1fc0cd3..05b6175c7 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraOperations.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraOperations.java @@ -183,11 +183,10 @@ public interface ReactiveCassandraOperations { * * @param entity The entity to insert, must not be {@literal null}. * @param options may be {@literal null}. - * @return the inserted entity or {@link Mono#empty()} if the {@code INSERT} operation was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem issuing the execution. */ - Mono insert(T entity, InsertOptions options) throws DataAccessException; - + Mono insert(Object entity, InsertOptions options) throws DataAccessException; /** * Update the given entity and emit the entity if the update was applied. * @@ -202,11 +201,10 @@ public interface ReactiveCassandraOperations { * * @param entity The entity to update, must not be {@literal null}. * @param options may be {@literal null}. - * @return the updated entity or {@link Mono#empty()} if the {@code UPDATE} operation was not applied. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem issuing the execution. */ - Mono update(T entity, UpdateOptions options) throws DataAccessException; - + Mono update(Object entity, UpdateOptions options) throws DataAccessException; /** * Remove the given object from the table by id. * @@ -231,11 +229,10 @@ public interface ReactiveCassandraOperations { * * @param entity must not be {@literal null}. * @param options may be {@literal null}. - * @return the deleted entity. + * @return the {@link WriteResult} for this operation. * @throws DataAccessException if there is any problem issuing the execution. */ - Mono delete(T entity, QueryOptions options) throws DataAccessException; - + Mono delete(Object entity, QueryOptions options) throws DataAccessException; /** * Execute a {@code TRUNCATE} query to remove all entities of a given class. * diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplate.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplate.java index d4c5d8e50..68fdd6008 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplate.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplate.java @@ -15,6 +15,8 @@ */ package org.springframework.data.cassandra.core; +import lombok.NonNull; +import lombok.Value; import reactor.core.publisher.Flux; import reactor.core.publisher.Mono; @@ -374,7 +376,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { */ @Override public Mono insert(T entity) { - return insert(entity, null); + return insert(entity, null).map(writeResult -> entity); } /* @@ -382,27 +384,13 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { * @see org.springframework.data.cassandra.core.ReactiveCassandraOperations#insert(java.lang.Object, org.springframework.data.cassandra.core.InsertOptions) */ @Override - public Mono insert(T entity, InsertOptions options) { + public Mono insert(Object entity, InsertOptions options) { Assert.notNull(entity, "Entity must not be null"); Insert insert = QueryUtils.createInsertQuery(getTableName(entity).toCql(), entity, options, getConverter()); - class InsertCallback implements ReactiveSessionCallback, CqlProvider { - - @Override - public Publisher doInSession(ReactiveSession session) throws DriverException, DataAccessException { - return session.execute(insert) - .flatMap(reactiveResultSet -> reactiveResultSet.wasApplied() ? Mono.just(entity) : Mono.empty()); - } - - @Override - public String getCql() { - return insert.toString(); - } - } - - return getReactiveCqlOperations().execute(new InsertCallback()).next(); + return getReactiveCqlOperations().execute(new StatementCallback(insert)).next(); } /* @@ -411,7 +399,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { */ @Override public Mono update(T entity) { - return update(entity, null); + return update(entity, null).map(writeResult -> entity); } /* @@ -419,27 +407,13 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { * @see org.springframework.data.cassandra.core.ReactiveCassandraOperations#update(java.lang.Object, org.springframework.data.cassandra.core.UpdateOptions) */ @Override - public Mono update(T entity, UpdateOptions options) { + public Mono update(Object entity, UpdateOptions options) { Assert.notNull(entity, "Entity must not be null"); Update update = QueryUtils.createUpdateQuery(getTableName(entity).toCql(), entity, options, converter); - class UpdateCallback implements ReactiveSessionCallback, CqlProvider { - - @Override - public Publisher doInSession(ReactiveSession session) throws DriverException, DataAccessException { - return session.execute(update) - .flatMap(reactiveResultSet -> reactiveResultSet.wasApplied() ? Mono.just(entity) : Mono.empty()); - } - - @Override - public String getCql() { - return update.toString(); - } - } - - return getReactiveCqlOperations().execute(new UpdateCallback()).next(); + return getReactiveCqlOperations().execute(new StatementCallback(update)).next(); } /* @@ -467,7 +441,7 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { */ @Override public Mono delete(T entity) { - return delete(entity, null); + return delete(entity, null).map(reactiveWriteResult -> entity); } /* @@ -475,27 +449,13 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { * @see org.springframework.data.cassandra.core.ReactiveCassandraOperations#delete(java.lang.Object, org.springframework.data.cql.core.QueryOptions) */ @Override - public Mono delete(T entity, QueryOptions options) { + public Mono delete(Object entity, QueryOptions options) { Assert.notNull(entity, "Entity must not be null"); Delete delete = QueryUtils.createDeleteQuery(getTableName(entity).toCql(), entity, options, getConverter()); - class DeleteCallback implements ReactiveSessionCallback, CqlProvider { - - @Override - public Publisher doInSession(ReactiveSession session) throws DriverException, DataAccessException { - return session.execute(delete) - .flatMap(reactiveResultSet -> reactiveResultSet.wasApplied() ? Mono.just(entity) : Mono.empty()); - } - - @Override - public String getCql() { - return delete.toString(); - } - } - - return getReactiveCqlOperations().execute(new DeleteCallback()).next(); + return getReactiveCqlOperations().execute(new StatementCallback(delete)).next(); } /* @@ -512,4 +472,26 @@ public class ReactiveCassandraTemplate implements ReactiveCassandraOperations { return getReactiveCqlOperations().execute(truncate).then(); } + + @Value + static class StatementCallback implements ReactiveSessionCallback, CqlProvider { + + @NonNull Statement statement; + + @Override + public Publisher doInSession(ReactiveSession session) throws DriverException, DataAccessException { + return session.execute(statement).flatMap(StatementCallback::toWriteResult); + } + + @Override + public String getCql() { + return statement.toString(); + } + + private static Mono toWriteResult(ReactiveResultSet resultSet) { + return resultSet.rows().collectList() + .map(rows -> new WriteResult(resultSet.getAllExecutionInfo(), resultSet.wasApplied(), rows)); + } + } + } diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/WriteResult.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/WriteResult.java new file mode 100644 index 000000000..bf1964fff --- /dev/null +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/WriteResult.java @@ -0,0 +1,97 @@ +/* + * Copyright 2017 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 java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.springframework.util.Assert; + +import com.datastax.driver.core.ExecutionInfo; +import com.datastax.driver.core.ResultSet; +import com.datastax.driver.core.Row; + +/** + * The result of a write operation. + * + * @author Mark Paluch + * @since 2.0 + * @see ResultSet + */ +public class WriteResult { + + private final List executionInfo; + private final boolean wasApplied; + private final List rows; + + WriteResult(List executionInfo, boolean wasApplied, List rows) { + + this.executionInfo = executionInfo; + this.wasApplied = wasApplied; + this.rows = rows; + } + + private WriteResult(ResultSet resultSet) { + + this.executionInfo = resultSet.getAllExecutionInfo(); + this.wasApplied = resultSet.wasApplied(); + + int limit = resultSet.getAvailableWithoutFetching(); + + List rows = new ArrayList<>(limit); + + for (int i = 0; i < limit; i++) { + rows.add(resultSet.one()); + } + + this.rows = Collections.unmodifiableList(rows); + } + + /** + * Create a {@link WriteResult} from {@link ResultSet}. + * + * @param resultSet must not be {@literal null}. + * @return the {@link WriteResult} for {@link ResultSet}. + */ + public static WriteResult of(ResultSet resultSet) { + + Assert.notNull(resultSet, "ResultSet must not be null"); + + return new WriteResult(resultSet); + } + + /** + * @return {@literal true} if the write was applied. + */ + public boolean wasApplied() { + return wasApplied; + } + + /** + * @return the list of {@link ExecutionInfo}. + */ + public List getExecutionInfo() { + return executionInfo; + } + + /** + * @return the {@link Row rows} returned by the write operation. + */ + public List getRows() { + return rows; + } +} diff --git a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java index 5563ba6fd..c36f22076 100644 --- a/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java +++ b/spring-data-cassandra/src/main/java/org/springframework/data/cassandra/repository/support/SimpleCassandraRepository.java @@ -123,7 +123,9 @@ public class SimpleCassandraRepository implements CassandraRepository implements CassandraRepository result = new ArrayList<>(); for (S entity : entities) { - - S saved = operations.insert(entity); - - if (saved != null) { - result.add(saved); - } + result.add(entity); + operations.insert(entity); } return result; diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateIntegrationTests.java index 87f49d4bf..036ddcba2 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateIntegrationTests.java @@ -114,9 +114,9 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea User user = new User("heisenberg", "Walter", "White"); - ListenableFuture inserted = template.insert(user, lwtOptions); + ListenableFuture inserted = template.insert(user, lwtOptions); - assertThat(getUninterruptibly(inserted)).isEqualTo(user); + assertThat(getUninterruptibly(inserted).wasApplied()).isTrue(); } @Test // DATACASS-250 @@ -130,9 +130,9 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea user.setFirstname("Walter Hartwell"); - ListenableFuture lwt = template.insert(user, lwtOptions); + ListenableFuture lwt = template.insert(user, lwtOptions); - assertThat(getUninterruptibly(lwt)).isNull(); + assertThat(getUninterruptibly(lwt).wasApplied()).isFalse(); assertThat(getUser(user.getId()).getFirstname()).isEqualTo("Walter"); } @@ -168,9 +168,9 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea User user = new User("heisenberg", "Walter", "White"); - ListenableFuture lwt = template.update(user, lwtOptions); + ListenableFuture lwt = template.update(user, lwtOptions); - assertThat(getUninterruptibly(lwt)).isNull(); + assertThat(getUninterruptibly(lwt).wasApplied()).isFalse(); assertThat(getUser(user.getId())).isNull(); } @@ -184,9 +184,9 @@ public class AsyncCassandraTemplateIntegrationTests extends AbstractKeyspaceCrea user.setFirstname("Walter Hartwell"); - ListenableFuture updated = template.update(user, lwtOptions); + ListenableFuture updated = template.update(user, lwtOptions); - assertThat(getUninterruptibly(updated)).isNotNull(); + assertThat(getUninterruptibly(updated).wasApplied()).isTrue(); assertThat(getUser(user.getId()).getFirstname()).isEqualTo("Walter Hartwell"); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateUnitTests.java index b510806a8..b5c204d4b 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateUnitTests.java @@ -256,18 +256,6 @@ public class AsyncCassandraTemplateUnitTests { } } - @Test // DATACASS-292 - public void insertShouldNotApplyInsert() { - - when(resultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - ListenableFuture future = template.insert(user); - - assertThat(getUninterruptibly(future)).isNull(); - } - @Test // DATACASS-292 public void updateShouldUpdateEntity() { @@ -302,18 +290,6 @@ public class AsyncCassandraTemplateUnitTests { } } - @Test // DATACASS-292 - public void updateShouldNotApplyUpdate() { - - when(resultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - ListenableFuture future = template.update(user); - - assertThat(getUninterruptibly(future)).isNull(); - } - @Test // DATACASS-292 public void deleteByIdShouldRemoveEntity() { @@ -361,18 +337,6 @@ public class AsyncCassandraTemplateUnitTests { } } - @Test // DATACASS-292 - public void deleteShouldNotApplyRemoval() { - - when(resultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - ListenableFuture future = template.delete(user); - - assertThat(getUninterruptibly(future)).isNull(); - } - @Test // DATACASS-292 public void truncateShouldRemoveEntities() { diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraBatchTemplateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraBatchTemplateIntegrationTests.java index 58cf1d0f2..d4e099b8f 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraBatchTemplateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraBatchTemplateIntegrationTests.java @@ -85,7 +85,7 @@ public class CassandraBatchTemplateIntegrationTests extends AbstractKeyspaceCrea walter.setAge(100); CassandraBatchOperations batchOperations = new CassandraBatchTemplate(template); - batchOperations.insert(Collections.singleton(walter), lwtOptions).insert(mike).execute(); + WriteResult writeResult = batchOperations.insert(Collections.singleton(walter), lwtOptions).insert(mike).execute(); Group loadedWalter = template.selectOneById(walter.getId(), Group.class); Group loadedMike = template.selectOneById(mike.getId(), Group.class); @@ -94,6 +94,9 @@ public class CassandraBatchTemplateIntegrationTests extends AbstractKeyspaceCrea assertThat(loadedWalter.getAge()).isEqualTo(42); assertThat(loadedMike).isNotNull(); + assertThat(writeResult.wasApplied()).isFalse(); + assertThat(writeResult.getExecutionInfo()).isNotEmpty(); + assertThat(writeResult.getRows()).isNotEmpty(); } @Test // DATACASS-288 @@ -180,8 +183,11 @@ public class CassandraBatchTemplateIntegrationTests extends AbstractKeyspaceCrea @Test // DATACASS-288 public void shouldUpdatesCollectionOfEntities() { - FlatGroup walter = template.insert(new FlatGroup("users", "0x1", "walter")); - FlatGroup mike = template.insert(new FlatGroup("users", "0x1", "mike")); + FlatGroup walter = new FlatGroup("users", "0x1", "walter"); + FlatGroup mike = new FlatGroup("users", "0x1", "mike"); + + template.insert(walter); + template.insert(mike); walter.setEmail("walter@white.com"); mike.setEmail("mike@sauls.com"); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java index 1e17afb09..f18adbbd0 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateIntegrationTests.java @@ -140,9 +140,8 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI assertThat(template.selectOneById(user.getId(), User.class)).isNull(); - User inserted = template.insert(user); + template.insert(user); - assertThat(inserted).isEqualTo(user); assertThat(template.selectOneById(user.getId(), User.class)).isEqualTo(user); } @@ -153,9 +152,9 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI User user = new User("heisenberg", "Walter", "White"); - User inserted = template.insert(user, lwtOptions); + template.insert(user, lwtOptions); - assertThat(inserted).isEqualTo(user); + assertThat(template.selectOneById(user.getId(), User.class)).isNotNull(); } @Test // DATACASS-250 @@ -169,9 +168,9 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI user.setFirstname("Walter Hartwell"); - User lwt = template.insert(user, lwtOptions); + WriteResult lwt = template.insert(user, lwtOptions); - assertThat(lwt).isNull(); + assertThat(lwt.wasApplied()).isFalse(); assertThat(template.selectOneById(user.getId(), User.class).getFirstname()).isEqualTo("Walter"); } @@ -194,9 +193,8 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI user.setFirstname("Walter Hartwell"); - User updated = template.update(user); + template.update(user); - assertThat(updated).isNotNull(); assertThat(template.selectOneById(user.getId(), User.class)).isEqualTo(user); } @@ -207,9 +205,9 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI User user = new User("heisenberg", "Walter", "White"); - User lwt = template.update(user, lwtOptions); + WriteResult lwt = template.update(user, lwtOptions); - assertThat(lwt).isNull(); + assertThat(lwt.wasApplied()).isFalse(); assertThat(template.selectOneById(user.getId(), User.class)).isNull(); } @@ -223,9 +221,9 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI user.setFirstname("Walter Hartwell"); - User updated = template.update(user, lwtOptions); + WriteResult lwt = template.update(user, lwtOptions); - assertThat(updated).isNotNull(); + assertThat(lwt.wasApplied()).isTrue(); assertThat(template.selectOneById(user.getId(), User.class).getFirstname()).isEqualTo("Walter Hartwell"); } @@ -275,9 +273,8 @@ public class CassandraTemplateIntegrationTests extends AbstractKeyspaceCreatingI User user = new User("heisenberg", "Walter", "White"); template.insert(user); - User deleted = template.delete(user); + template.delete(user); - assertThat(deleted).isNotNull(); assertThat(template.selectOneById(user.getId(), User.class)).isNull(); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateUnitTests.java index 797a2f49c..ed0d8686a 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateUnitTests.java @@ -196,9 +196,8 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User inserted = template.insert(user); + template.insert(user); - assertThat(inserted).isEqualTo(user); verify(session).execute(statementCaptor.capture()); assertThat(statementCaptor.getValue().toString()) .isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White');"); @@ -213,9 +212,8 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User inserted = template.insert(user, insertOptions); + template.insert(user, insertOptions); - assertThat(inserted).isEqualTo(user); verify(session).execute(statementCaptor.capture()); assertThat(statementCaptor.getValue().toString()) .isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','heisenberg','White') IF NOT EXISTS;"); @@ -243,9 +241,9 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User inserted = template.insert(user); + WriteResult writeResult = template.insert(user, InsertOptions.builder().build()); - assertThat(inserted).isNull(); + assertThat(writeResult.wasApplied()).isFalse(); } @Test // DATACASS-292 @@ -255,9 +253,8 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User updated = template.update(user); + template.update(user); - assertThat(updated).isEqualTo(user); verify(session).execute(statementCaptor.capture()); assertThat(statementCaptor.getValue().toString()) .isEqualTo("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg';"); @@ -272,9 +269,9 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User updated = template.update(user, updateOptions); + WriteResult writeResult = template.update(user, updateOptions); - assertThat(updated).isEqualTo(user); + assertThat(writeResult.wasApplied()).isTrue(); verify(session).execute(statementCaptor.capture()); assertThat(statementCaptor.getValue().toString()) .isEqualTo("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg' IF EXISTS;"); @@ -295,18 +292,6 @@ public class CassandraTemplateUnitTests { } } - @Test // DATACASS-292 - public void updateShouldNotApplyUpdate() { - - when(resultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - User updated = template.update(user); - - assertThat(updated).isNull(); - } - @Test // DATACASS-292 public void deleteByIdShouldRemoveEntity() { @@ -328,9 +313,8 @@ public class CassandraTemplateUnitTests { User user = new User("heisenberg", "Walter", "White"); - User deleted = template.delete(user); + template.delete(user); - assertThat(deleted).isEqualTo(user); verify(session).execute(statementCaptor.capture()); assertThat(statementCaptor.getValue().toString()).isEqualTo("DELETE FROM users WHERE id='heisenberg';"); } @@ -350,18 +334,6 @@ public class CassandraTemplateUnitTests { } } - @Test // DATACASS-292 - public void deleteShouldNotApplyRemoval() { - - when(resultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - User deleted = template.delete(user); - - assertThat(deleted).isNull(); - } - @Test // DATACASS-292 public void truncateShouldRemoveEntities() { diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateIntegrationTests.java index e996606b9..8aeeb8da2 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateIntegrationTests.java @@ -83,9 +83,9 @@ public class ReactiveCassandraTemplateIntegrationTests extends AbstractKeyspaceC User user = new User("heisenberg", "Walter", "White"); - Mono inserted = template.insert(user, lwtOptions); + Mono inserted = template.insert(user, lwtOptions); - StepVerifier.create(inserted).expectNext(user).verifyComplete(); + StepVerifier.create(inserted.map(WriteResult::wasApplied)).expectNext(true).verifyComplete(); } @Test // DATACASS-250 @@ -95,11 +95,13 @@ public class ReactiveCassandraTemplateIntegrationTests extends AbstractKeyspaceC User user = new User("heisenberg", "Walter", "White"); - StepVerifier.create(template.insert(user, lwtOptions)).expectNext(user).verifyComplete(); + StepVerifier.create(template.insert(user, lwtOptions).map(WriteResult::wasApplied)).expectNext(true) + .verifyComplete(); user.setFirstname("Walter Hartwell"); - StepVerifier.create(template.insert(user, lwtOptions)).verifyComplete(); + StepVerifier.create(template.insert(user, lwtOptions).map(WriteResult::wasApplied)).expectNext(false) + .verifyComplete(); verifyUser(user.getId()).consumeNextWith(it -> assertThat(it.getFirstname()).isEqualTo("Walter")).verifyComplete(); } @@ -135,7 +137,8 @@ public class ReactiveCassandraTemplateIntegrationTests extends AbstractKeyspaceC User user = new User("heisenberg", "Walter", "White"); - StepVerifier.create(template.update(user, lwtOptions)).verifyComplete(); + StepVerifier.create(template.update(user, lwtOptions).map(WriteResult::wasApplied)).expectNext(false) + .verifyComplete(); verifyUser(user.getId()).verifyComplete(); } diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateUnitTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateUnitTests.java index b95392b79..13de91a02 100644 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateUnitTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/ReactiveCassandraTemplateUnitTests.java @@ -166,6 +166,7 @@ public class ReactiveCassandraTemplateUnitTests { public void insertShouldInsertEntity() { when(reactiveResultSet.wasApplied()).thenReturn(true); + when(reactiveResultSet.rows()).thenReturn(Flux.just(row)); User user = new User("heisenberg", "Walter", "White"); StepVerifier.create(template.insert(user)).expectNext(user).verifyComplete(); @@ -189,20 +190,11 @@ public class ReactiveCassandraTemplateUnitTests { }).verify(); } - @Test // DATACASS-335 - public void insertShouldNotApplyInsert() { - - when(reactiveResultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - StepVerifier.create(template.insert(user)).verifyComplete(); - } - @Test // DATACASS-335 public void updateShouldUpdateEntity() { when(reactiveResultSet.wasApplied()).thenReturn(true); + when(reactiveResultSet.rows()).thenReturn(Flux.just(row)); User user = new User("heisenberg", "Walter", "White"); @@ -213,20 +205,11 @@ public class ReactiveCassandraTemplateUnitTests { .isEqualTo("UPDATE users SET firstname='Walter',lastname='White' WHERE id='heisenberg';"); } - @Test // DATACASS-335 - public void updateShouldNotApplyUpdate() { - - when(reactiveResultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - StepVerifier.create(template.update(user)).verifyComplete(); - } - @Test // DATACASS-335 public void deleteShouldRemoveEntity() { when(reactiveResultSet.wasApplied()).thenReturn(true); + when(reactiveResultSet.rows()).thenReturn(Flux.just(row)); User user = new User("heisenberg", "Walter", "White"); @@ -236,16 +219,6 @@ public class ReactiveCassandraTemplateUnitTests { assertThat(statementCaptor.getValue().toString()).isEqualTo("DELETE FROM users WHERE id='heisenberg';"); } - @Test // DATACASS-335 - public void deleteShouldNotApplyRemoval() { - - when(reactiveResultSet.wasApplied()).thenReturn(false); - - User user = new User("heisenberg", "Walter", "White"); - - StepVerifier.create(template.delete(user)).verifyComplete(); - } - @Test // DATACASS-335 public void truncateShouldRemoveEntities() { diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/proxy/CassandraTemplateMapIdProxyDelegateIntegrationTests.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/proxy/CassandraTemplateMapIdProxyDelegateIntegrationTests.java index d870de3ed..ac32fb4b3 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/proxy/CassandraTemplateMapIdProxyDelegateIntegrationTests.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/proxy/CassandraTemplateMapIdProxyDelegateIntegrationTests.java @@ -58,23 +58,20 @@ public class CassandraTemplateMapIdProxyDelegateIntegrationTests extends Abstrac // insert SinglePkc inserted = new SinglePkc(uuid()); inserted.setValue(uuid()); - SinglePkc saved = operations.insert(inserted); - assertThat(inserted).isSameAs(saved); + operations.insert(inserted); // select - SinglePkcId id = id(SinglePkcId.class).key(saved.getKey()); + SinglePkcId id = id(SinglePkcId.class).key(inserted.getKey()); SinglePkc selected = operations.selectOneById(id, SinglePkc.class); - assertThat(saved).isNotSameAs(selected); - assertThat(selected.getKey()).isEqualTo(saved.getKey()); - assertThat(selected.getValue()).isEqualTo(saved.getValue()); + assertThat(inserted).isNotSameAs(selected); + assertThat(selected.getKey()).isEqualTo(inserted.getKey()); + assertThat(selected.getValue()).isEqualTo(inserted.getValue()); // update selected.setValue(uuid()); - SinglePkc updated = operations.update(selected); - assertThat(selected).isSameAs(updated); + operations.update(selected); - selected = operations.selectOneById(id, SinglePkc.class); - assertThat(updated).isNotSameAs(selected); + SinglePkc updated = operations.selectOneById(id, SinglePkc.class); assertThat(selected.getValue()).isEqualTo(updated.getValue()); // delete @@ -122,23 +119,20 @@ public class CassandraTemplateMapIdProxyDelegateIntegrationTests extends Abstrac // insert MultiPkc inserted = new MultiPkc(uuid(), uuid()); inserted.setValue(uuid()); - MultiPkc saved = operations.insert(inserted); - assertThat(inserted).isSameAs(saved); + operations.insert(inserted); // select - MultiPkcId id = id(MultiPkcId.class).key0(saved.getKey0()).key1(saved.getKey1()); + MultiPkcId id = id(MultiPkcId.class).key0(inserted.getKey0()).key1(inserted.getKey1()); MultiPkc selected = operations.selectOneById(id, MultiPkc.class); - assertThat(saved).isNotSameAs(selected); - assertThat(selected.getKey0()).isEqualTo(saved.getKey0()); - assertThat(selected.getKey1()).isEqualTo(saved.getKey1()); - assertThat(selected.getValue()).isEqualTo(saved.getValue()); + assertThat(selected.getKey0()).isEqualTo(inserted.getKey0()); + assertThat(selected.getKey1()).isEqualTo(inserted.getKey1()); + assertThat(selected.getValue()).isEqualTo(inserted.getValue()); // update selected.setValue(uuid()); - MultiPkc updated = operations.update(selected); - assertThat(selected).isSameAs(updated); + operations.update(selected); - selected = operations.selectOneById(id, MultiPkc.class); + MultiPkc updated = operations.selectOneById(id, MultiPkc.class); assertThat(updated).isNotSameAs(selected); assertThat(selected.getValue()).isEqualTo(updated.getValue()); diff --git a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/template/CassandraTemplateMapIdIntegrationTest.java b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/template/CassandraTemplateMapIdIntegrationTest.java index cf449d1c1..5005d9734 100755 --- a/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/template/CassandraTemplateMapIdIntegrationTest.java +++ b/spring-data-cassandra/src/test/java/org/springframework/data/cassandra/test/integration/mapping/mapid/template/CassandraTemplateMapIdIntegrationTest.java @@ -13,7 +13,6 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - package org.springframework.data.cassandra.test.integration.mapping.mapid.template; import static org.assertj.core.api.Assertions.*; @@ -58,22 +57,19 @@ public class CassandraTemplateMapIdIntegrationTest extends AbstractKeyspaceCreat // insert SinglePkc inserted = new SinglePkc(uuid()); inserted.setValue(uuid()); - SinglePkc saved = operations.insert(inserted); - assertThat(inserted).isSameAs(saved); + operations.insert(inserted); // select - MapId id = id("key", saved.getKey()); + MapId id = id("key", inserted.getKey()); SinglePkc selected = operations.selectOneById(id, SinglePkc.class); - assertThat(saved).isNotSameAs(selected); - assertThat(selected.getKey()).isEqualTo(saved.getKey()); - assertThat(selected.getValue()).isEqualTo(saved.getValue()); + assertThat(selected.getKey()).isEqualTo(inserted.getKey()); + assertThat(selected.getValue()).isEqualTo(inserted.getValue()); // update selected.setValue(uuid()); - SinglePkc updated = operations.update(selected); - assertThat(selected).isSameAs(updated); + operations.update(selected); - selected = operations.selectOneById(id, SinglePkc.class); + SinglePkc updated = operations.selectOneById(id, SinglePkc.class); assertThat(updated).isNotSameAs(selected); assertThat(selected.getValue()).isEqualTo(updated.getValue()); @@ -110,37 +106,6 @@ public class CassandraTemplateMapIdIntegrationTest extends AbstractKeyspaceCreat } } - @Test - public void testMultiPkc() { - - // insert - MultiPkc inserted = new MultiPkc(uuid(), uuid()); - inserted.setValue(uuid()); - MultiPkc saved = operations.insert(inserted); - assertThat(inserted).isSameAs(saved); - - // select - MapId id = id("key0", saved.getKey0()).with("key1", saved.getKey1()); - MultiPkc selected = operations.selectOneById(id, MultiPkc.class); - assertThat(saved).isNotSameAs(selected); - assertThat(selected.getKey0()).isEqualTo(saved.getKey0()); - assertThat(selected.getKey1()).isEqualTo(saved.getKey1()); - assertThat(selected.getValue()).isEqualTo(saved.getValue()); - - // update - selected.setValue(uuid()); - MultiPkc updated = operations.update(selected); - assertThat(selected).isSameAs(updated); - - selected = operations.selectOneById(id, MultiPkc.class); - assertThat(updated).isNotSameAs(selected); - assertThat(selected.getValue()).isEqualTo(updated.getValue()); - - // delete - operations.delete(selected); - assertThat(operations.selectOneById(id, MultiPkc.class)).isNull(); - } - @Table public static class MultiPkc { diff --git a/src/main/asciidoc/reference/cassandra.adoc b/src/main/asciidoc/reference/cassandra.adoc index ce6d13102..5641ff58f 100644 --- a/src/main/asciidoc/reference/cassandra.adoc +++ b/src/main/asciidoc/reference/cassandra.adoc @@ -1159,13 +1159,13 @@ Person qp = cassandraTemplate.selectOne(query(where("age").is(33)), Person.class The insert/save operations available to you are listed below. -* `T` *insert* `(T objectToSave)` Insert the object in an Apache Cassandra table. -* `T` *insert* `(T objectToSave, InsertOptions options)` Insert the object in an Apache Cassandra table applying `InsertOptions`. +* `void` *insert* `(Object objectToSave)` Insert the object in an Apache Cassandra table. +* `WriteResult` *insert* `(Object objectToSave, InsertOptions options)` Insert the object in an Apache Cassandra table applying `InsertOptions`. A similar set of update operations is listed below -* `T` *update* `(T objectToSave)` Update the object in an Apache Cassandra table. -* `T` *update* `(T objectToSave, UpdateOptions options)` Update the object in an Apache Cassandra table applying `UpdateOptions`. +* `void` *update* `(Object objectToSave)` Update the object in an Apache Cassandra table. +* `WriteResult` *update* `(Object objectToSave, UpdateOptions options)` Update the object in an Apache Cassandra table applying `UpdateOptions`. Then, there is always the old fashioned way. You can write your own CQL statements. You can configure with `InsertOptions` and `UpdateOptions` additional options such as TTL, consistency level and lightweight transactions.