Skip to content

Commit b25a67c

Browse files
committed
Use BeforeConvertCallback.onBeforeConvert(…) outcome for the actual insert.
We now use correctly the result of the `onBeforeConvert` callback for insert instead of the original entity. Closes #1295
1 parent 7dca59b commit b25a67c

File tree

5 files changed

+155
-99
lines changed

5 files changed

+155
-99
lines changed

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/AsyncCassandraTemplate.java

+19-20
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,24 @@
2525
import java.util.stream.Collectors;
2626
import java.util.stream.StreamSupport;
2727

28+
import com.datastax.oss.driver.api.core.CqlIdentifier;
29+
import com.datastax.oss.driver.api.core.CqlSession;
30+
import com.datastax.oss.driver.api.core.DriverException;
31+
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
32+
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
33+
import com.datastax.oss.driver.api.core.cql.BoundStatement;
34+
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
35+
import com.datastax.oss.driver.api.core.cql.ResultSet;
36+
import com.datastax.oss.driver.api.core.cql.Row;
37+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
38+
import com.datastax.oss.driver.api.core.cql.Statement;
39+
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
40+
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
41+
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
42+
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
43+
import com.datastax.oss.driver.api.querybuilder.select.Select;
44+
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
45+
import com.datastax.oss.driver.api.querybuilder.update.Update;
2846
import org.apache.commons.logging.Log;
2947
import org.apache.commons.logging.LogFactory;
3048

@@ -64,25 +82,6 @@
6482
import org.springframework.lang.Nullable;
6583
import org.springframework.util.Assert;
6684

67-
import com.datastax.oss.driver.api.core.CqlIdentifier;
68-
import com.datastax.oss.driver.api.core.CqlSession;
69-
import com.datastax.oss.driver.api.core.DriverException;
70-
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
71-
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
72-
import com.datastax.oss.driver.api.core.cql.BoundStatement;
73-
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
74-
import com.datastax.oss.driver.api.core.cql.ResultSet;
75-
import com.datastax.oss.driver.api.core.cql.Row;
76-
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
77-
import com.datastax.oss.driver.api.core.cql.Statement;
78-
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
79-
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
80-
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
81-
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
82-
import com.datastax.oss.driver.api.querybuilder.select.Select;
83-
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
84-
import com.datastax.oss.driver.api.querybuilder.update.Update;
85-
8685
/**
8786
* Primary implementation of {@link AsyncCassandraOperations}. It simplifies the use of asynchronous Cassandra usage and
8887
* helps to avoid common errors. It executes core Cassandra workflow. This class executes CQL queries or updates,
@@ -572,7 +571,7 @@ private <T> CompletableFuture<EntityWriteResult<T>> doInsert(T entity, WriteOpti
572571
getConverter().getConversionService());
573572
CassandraPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(entity.getClass());
574573

575-
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : entity;
574+
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : source.getBean();
576575

577576
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options, persistentEntity,
578577
tableName);

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/CassandraTemplate.java

+19-20
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,24 @@
2121
import java.util.function.Supplier;
2222
import java.util.stream.Stream;
2323

24+
import com.datastax.oss.driver.api.core.CqlIdentifier;
25+
import com.datastax.oss.driver.api.core.CqlSession;
26+
import com.datastax.oss.driver.api.core.DriverException;
27+
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
28+
import com.datastax.oss.driver.api.core.cql.BatchType;
29+
import com.datastax.oss.driver.api.core.cql.BoundStatement;
30+
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
31+
import com.datastax.oss.driver.api.core.cql.ResultSet;
32+
import com.datastax.oss.driver.api.core.cql.Row;
33+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
34+
import com.datastax.oss.driver.api.core.cql.Statement;
35+
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
36+
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
37+
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
38+
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
39+
import com.datastax.oss.driver.api.querybuilder.select.Select;
40+
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
41+
import com.datastax.oss.driver.api.querybuilder.update.Update;
2442
import org.apache.commons.logging.Log;
2543
import org.apache.commons.logging.LogFactory;
2644

@@ -62,25 +80,6 @@
6280
import org.springframework.lang.Nullable;
6381
import org.springframework.util.Assert;
6482

65-
import com.datastax.oss.driver.api.core.CqlIdentifier;
66-
import com.datastax.oss.driver.api.core.CqlSession;
67-
import com.datastax.oss.driver.api.core.DriverException;
68-
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
69-
import com.datastax.oss.driver.api.core.cql.BatchType;
70-
import com.datastax.oss.driver.api.core.cql.BoundStatement;
71-
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
72-
import com.datastax.oss.driver.api.core.cql.ResultSet;
73-
import com.datastax.oss.driver.api.core.cql.Row;
74-
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
75-
import com.datastax.oss.driver.api.core.cql.Statement;
76-
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
77-
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
78-
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
79-
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
80-
import com.datastax.oss.driver.api.querybuilder.select.Select;
81-
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
82-
import com.datastax.oss.driver.api.querybuilder.update.Update;
83-
8483
/**
8584
* Primary implementation of {@link CassandraOperations}. It simplifies the use of Cassandra usage and helps to avoid
8685
* common errors. It executes core Cassandra workflow. This class executes CQL queries or updates, initiating iteration
@@ -603,7 +602,7 @@ <T> EntityWriteResult<T> doInsert(T entity, WriteOptions options, CqlIdentifier
603602
AdaptibleEntity<T> source = getEntityOperations().forEntity(maybeCallBeforeConvert(entity, tableName),
604603
getConverter().getConversionService());
605604

606-
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : entity;
605+
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : source.getBean();
607606

608607
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options,
609608
source.getPersistentEntity(), tableName);

spring-data-cassandra/src/main/java/org/springframework/data/cassandra/core/legacy/AsyncCassandraTemplate.java

+19-20
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,24 @@
2424
import java.util.stream.Collectors;
2525
import java.util.stream.StreamSupport;
2626

27+
import com.datastax.oss.driver.api.core.CqlIdentifier;
28+
import com.datastax.oss.driver.api.core.CqlSession;
29+
import com.datastax.oss.driver.api.core.DriverException;
30+
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
31+
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
32+
import com.datastax.oss.driver.api.core.cql.BoundStatement;
33+
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
34+
import com.datastax.oss.driver.api.core.cql.ResultSet;
35+
import com.datastax.oss.driver.api.core.cql.Row;
36+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
37+
import com.datastax.oss.driver.api.core.cql.Statement;
38+
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
39+
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
40+
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
41+
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
42+
import com.datastax.oss.driver.api.querybuilder.select.Select;
43+
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
44+
import com.datastax.oss.driver.api.querybuilder.update.Update;
2745
import org.apache.commons.logging.Log;
2846
import org.apache.commons.logging.LogFactory;
2947

@@ -86,25 +104,6 @@
86104
import org.springframework.util.Assert;
87105
import org.springframework.util.concurrent.ListenableFuture;
88106

89-
import com.datastax.oss.driver.api.core.CqlIdentifier;
90-
import com.datastax.oss.driver.api.core.CqlSession;
91-
import com.datastax.oss.driver.api.core.DriverException;
92-
import com.datastax.oss.driver.api.core.config.DefaultDriverOption;
93-
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
94-
import com.datastax.oss.driver.api.core.cql.BoundStatement;
95-
import com.datastax.oss.driver.api.core.cql.PreparedStatement;
96-
import com.datastax.oss.driver.api.core.cql.ResultSet;
97-
import com.datastax.oss.driver.api.core.cql.Row;
98-
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
99-
import com.datastax.oss.driver.api.core.cql.Statement;
100-
import com.datastax.oss.driver.api.querybuilder.QueryBuilder;
101-
import com.datastax.oss.driver.api.querybuilder.delete.Delete;
102-
import com.datastax.oss.driver.api.querybuilder.insert.Insert;
103-
import com.datastax.oss.driver.api.querybuilder.insert.RegularInsert;
104-
import com.datastax.oss.driver.api.querybuilder.select.Select;
105-
import com.datastax.oss.driver.api.querybuilder.truncate.Truncate;
106-
import com.datastax.oss.driver.api.querybuilder.update.Update;
107-
108107
/**
109108
* Primary implementation of {@link AsyncCassandraOperations}. It simplifies the use of asynchronous Cassandra usage and
110109
* helps to avoid common errors. It executes core Cassandra workflow. This class executes CQL queries or updates,
@@ -602,7 +601,7 @@ private <T> ListenableFuture<EntityWriteResult<T>> doInsert(T entity, WriteOptio
602601
getConverter().getConversionService());
603602
CassandraPersistentEntity<?> persistentEntity = getRequiredPersistentEntity(entity.getClass());
604603

605-
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : entity;
604+
T entityToUse = source.isVersionedEntity() ? source.initializeVersionProperty() : source.getBean();
606605

607606
StatementBuilder<RegularInsert> builder = getStatementFactory().insert(entityToUse, options, persistentEntity,
608607
tableName);

spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/AsyncCassandraTemplateUnitTests.java

+39-19
Original file line numberDiff line numberDiff line change
@@ -15,18 +15,26 @@
1515
*/
1616
package org.springframework.data.cassandra.core;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
import static org.mockito.ArgumentMatchers.*;
20-
import static org.mockito.Mockito.*;
21-
import static org.springframework.data.cassandra.core.query.Criteria.*;
22-
2318
import java.util.ArrayList;
2419
import java.util.Collections;
2520
import java.util.List;
2621
import java.util.concurrent.CompletableFuture;
2722
import java.util.concurrent.ExecutionException;
2823
import java.util.concurrent.Future;
2924

25+
import com.datastax.oss.driver.api.core.CqlIdentifier;
26+
import com.datastax.oss.driver.api.core.CqlSession;
27+
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
28+
import com.datastax.oss.driver.api.core.context.DriverContext;
29+
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
30+
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
31+
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
32+
import com.datastax.oss.driver.api.core.cql.Row;
33+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
34+
import com.datastax.oss.driver.api.core.cql.Statement;
35+
import com.datastax.oss.driver.api.core.type.DataTypes;
36+
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
37+
import com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry;
3038
import org.junit.jupiter.api.BeforeEach;
3139
import org.junit.jupiter.api.Test;
3240
import org.junit.jupiter.api.extension.ExtendWith;
@@ -47,19 +55,10 @@
4755
import org.springframework.data.cassandra.domain.VersionedUser;
4856
import org.springframework.data.mapping.callback.EntityCallbacks;
4957

50-
import com.datastax.oss.driver.api.core.CqlIdentifier;
51-
import com.datastax.oss.driver.api.core.CqlSession;
52-
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
53-
import com.datastax.oss.driver.api.core.context.DriverContext;
54-
import com.datastax.oss.driver.api.core.cql.AsyncResultSet;
55-
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
56-
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
57-
import com.datastax.oss.driver.api.core.cql.Row;
58-
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
59-
import com.datastax.oss.driver.api.core.cql.Statement;
60-
import com.datastax.oss.driver.api.core.type.DataTypes;
61-
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
62-
import com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry;
58+
import static org.assertj.core.api.Assertions.*;
59+
import static org.mockito.ArgumentMatchers.*;
60+
import static org.mockito.Mockito.*;
61+
import static org.springframework.data.cassandra.core.query.Criteria.*;
6362

6463
/**
6564
* Unit tests for {@link AsyncCassandraTemplate}.
@@ -325,7 +324,28 @@ void insertShouldInsertEntity() {
325324
assertThat(beforeSave).isSameAs(user);
326325
}
327326

328-
@Test // DATACASS-618
327+
@Test
328+
// GH-1295
329+
void insertShouldConsiderEntityAfterCallback() {
330+
331+
when(resultSet.wasApplied()).thenReturn(true);
332+
333+
User user = new User("heisenberg", "Walter", "White");
334+
335+
EntityCallbacks callbacks = EntityCallbacks.create();
336+
callbacks.addEntityCallback((BeforeConvertCallback<Object>) (entity, tableName) -> new User("ww", "Walter", "White"));
337+
template.setEntityCallbacks(callbacks);
338+
339+
CompletableFuture<User> future = template.insert(user);
340+
341+
assertThat(getUninterruptibly(future)).isNotSameAs(user);
342+
verify(session).executeAsync(statementCaptor.capture());
343+
assertThat(render(statementCaptor.getValue()))
344+
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','ww','White')");
345+
}
346+
347+
@Test
348+
// DATACASS-618
329349
void insertShouldInsertVersionedEntity() {
330350

331351
when(resultSet.wasApplied()).thenReturn(true);

spring-data-cassandra/src/test/java/org/springframework/data/cassandra/core/CassandraTemplateUnitTests.java

+59-20
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,22 @@
1515
*/
1616
package org.springframework.data.cassandra.core;
1717

18-
import static org.assertj.core.api.Assertions.*;
19-
import static org.mockito.ArgumentMatchers.*;
20-
import static org.mockito.Mockito.*;
21-
import static org.springframework.data.cassandra.core.query.Criteria.*;
22-
2318
import java.util.Collections;
2419
import java.util.List;
2520

21+
import com.datastax.oss.driver.api.core.CqlIdentifier;
22+
import com.datastax.oss.driver.api.core.CqlSession;
23+
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
24+
import com.datastax.oss.driver.api.core.context.DriverContext;
25+
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
26+
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
27+
import com.datastax.oss.driver.api.core.cql.ResultSet;
28+
import com.datastax.oss.driver.api.core.cql.Row;
29+
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
30+
import com.datastax.oss.driver.api.core.cql.Statement;
31+
import com.datastax.oss.driver.api.core.type.DataTypes;
32+
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
33+
import com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry;
2634
import org.junit.jupiter.api.BeforeEach;
2735
import org.junit.jupiter.api.Test;
2836
import org.junit.jupiter.api.extension.ExtendWith;
@@ -43,19 +51,10 @@
4351
import org.springframework.data.cassandra.domain.VersionedUser;
4452
import org.springframework.data.mapping.callback.EntityCallbacks;
4553

46-
import com.datastax.oss.driver.api.core.CqlIdentifier;
47-
import com.datastax.oss.driver.api.core.CqlSession;
48-
import com.datastax.oss.driver.api.core.NoNodeAvailableException;
49-
import com.datastax.oss.driver.api.core.context.DriverContext;
50-
import com.datastax.oss.driver.api.core.cql.ColumnDefinition;
51-
import com.datastax.oss.driver.api.core.cql.ColumnDefinitions;
52-
import com.datastax.oss.driver.api.core.cql.ResultSet;
53-
import com.datastax.oss.driver.api.core.cql.Row;
54-
import com.datastax.oss.driver.api.core.cql.SimpleStatement;
55-
import com.datastax.oss.driver.api.core.cql.Statement;
56-
import com.datastax.oss.driver.api.core.type.DataTypes;
57-
import com.datastax.oss.driver.api.core.type.codec.registry.CodecRegistry;
58-
import com.datastax.oss.driver.internal.core.type.codec.registry.DefaultCodecRegistry;
54+
import static org.assertj.core.api.Assertions.*;
55+
import static org.mockito.ArgumentMatchers.*;
56+
import static org.mockito.Mockito.*;
57+
import static org.springframework.data.cassandra.core.query.Criteria.*;
5958

6059
/**
6160
* Unit tests for {@link CassandraTemplate}.
@@ -307,7 +306,27 @@ void insertShouldInsertEntity() {
307306
assertThat(beforeSave).isSameAs(user);
308307
}
309308

310-
@Test // DATACASS-618
309+
@Test
310+
// GH-1295
311+
void insertShouldConsiderEntityAfterCallback() {
312+
313+
when(resultSet.wasApplied()).thenReturn(true);
314+
315+
User user = new User("heisenberg", "Walter", "White");
316+
317+
EntityCallbacks callbacks = EntityCallbacks.create();
318+
callbacks.addEntityCallback((BeforeConvertCallback<Object>) (entity, tableName) -> new User("ww", "Walter", "White"));
319+
template.setEntityCallbacks(callbacks);
320+
321+
template.insert(user);
322+
323+
verify(session).execute(statementCaptor.capture());
324+
assertThat(render(statementCaptor.getValue()))
325+
.isEqualTo("INSERT INTO users (firstname,id,lastname) VALUES ('Walter','ww','White')");
326+
}
327+
328+
@Test
329+
// DATACASS-618
311330
void insertShouldInsertVersionedEntity() {
312331

313332
when(resultSet.wasApplied()).thenReturn(true);
@@ -323,7 +342,27 @@ void insertShouldInsertVersionedEntity() {
323342
assertThat(beforeSave).isSameAs(user);
324343
}
325344

326-
@Test // DATACASS-250
345+
@Test
346+
// GH-1295
347+
void insertShouldInsertVersionedEntityAfterCallback() {
348+
349+
when(resultSet.wasApplied()).thenReturn(true);
350+
351+
VersionedUser user = new VersionedUser("heisenberg", "Walter", "White");
352+
353+
EntityCallbacks callbacks = EntityCallbacks.create();
354+
callbacks.addEntityCallback((BeforeConvertCallback<Object>) (entity, tableName) -> new VersionedUser("ww", "Walter", "White"));
355+
template.setEntityCallbacks(callbacks);
356+
357+
template.insert(user);
358+
359+
verify(session).execute(statementCaptor.capture());
360+
assertThat(render(statementCaptor.getValue())).isEqualTo(
361+
"INSERT INTO vusers (firstname,id,lastname,version) VALUES ('Walter','ww','White',0) IF NOT EXISTS");
362+
}
363+
364+
@Test
365+
// DATACASS-250
327366
void insertShouldInsertWithOptionsEntity() {
328367

329368
InsertOptions insertOptions = InsertOptions.builder().withIfNotExists().build();

0 commit comments

Comments
 (0)