Skip to content

Commit 5a024fb

Browse files
committed
Move default Id value cleanup on insert from Converter into R2dbcEntityTemplate.
We now check in R2dbcEntityTemplate whether we need to skip the Id value if its value is null or a primitive using its default. Previously, the check was located in the converter. Converting an entity afteri ncrementing the version of a versioned entity would write the Id value as the entity was no longer considered to be new. Closes #557.
1 parent fab6d76 commit 5a024fb

File tree

4 files changed

+90
-32
lines changed

4 files changed

+90
-32
lines changed

src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java

Lines changed: 0 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -379,33 +379,10 @@ private void writeSimpleInternal(OutboundRow sink, Object value, boolean isNew,
379379

380380
Object result = getPotentiallyConvertedSimpleWrite(value);
381381

382-
if (property.isIdProperty() && isNew) {
383-
if (shouldSkipIdValue(result, property)) {
384-
return;
385-
}
386-
}
387-
388382
sink.put(property.getColumnName(),
389383
Parameter.fromOrEmpty(result, getPotentiallyConvertedSimpleNullType(property.getType())));
390384
}
391385

392-
private boolean shouldSkipIdValue(@Nullable Object value, RelationalPersistentProperty property) {
393-
394-
if (value == null) {
395-
return true;
396-
}
397-
398-
if (!property.getType().isPrimitive()) {
399-
return value == null;
400-
}
401-
402-
if (value instanceof Number) {
403-
return ((Number) value).longValue() == 0L;
404-
}
405-
406-
return false;
407-
}
408-
409386
private void writePropertyInternal(OutboundRow sink, Object value, boolean isNew,
410387
RelationalPersistentProperty property) {
411388

src/main/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplate.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -546,11 +546,41 @@ <T> Mono<T> doInsert(T entity, SqlIdentifier tableName) {
546546

547547
OutboundRow outboundRow = dataAccessStrategy.getOutboundRow(initializedEntity);
548548

549+
potentiallyRemoveId(persistentEntity, outboundRow);
550+
549551
return maybeCallBeforeSave(initializedEntity, outboundRow, tableName) //
550552
.flatMap(entityToSave -> doInsert(entityToSave, tableName, outboundRow));
551553
});
552554
}
553555

556+
private void potentiallyRemoveId(RelationalPersistentEntity<?> persistentEntity, OutboundRow outboundRow) {
557+
558+
RelationalPersistentProperty idProperty = persistentEntity.getIdProperty();
559+
if (idProperty == null) {
560+
return;
561+
}
562+
563+
SqlIdentifier columnName = idProperty.getColumnName();
564+
Parameter parameter = outboundRow.get(columnName);
565+
566+
if (shouldSkipIdValue(parameter, idProperty)) {
567+
outboundRow.remove(columnName);
568+
}
569+
}
570+
571+
private boolean shouldSkipIdValue(@Nullable Parameter value, RelationalPersistentProperty property) {
572+
573+
if (value == null || value.getValue() == null) {
574+
return true;
575+
}
576+
577+
if (value.getValue() instanceof Number) {
578+
return ((Number) value.getValue()).longValue() == 0L;
579+
}
580+
581+
return false;
582+
}
583+
554584
private <T> Mono<T> doInsert(T entity, SqlIdentifier tableName, OutboundRow outboundRow) {
555585

556586
StatementMapper mapper = dataAccessStrategy.getStatementMapper();

src/test/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverterUnitTests.java

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -212,15 +212,6 @@ public void shouldReadTopLevelEntityWithConverter() {
212212
assertThat(result.entity).isNotNull();
213213
}
214214

215-
@Test // gh-402
216-
public void writeShouldSkipPrimitiveIdIfValueIsZero() {
217-
218-
OutboundRow row = new OutboundRow();
219-
converter.write(new WithPrimitiveId(0), row);
220-
221-
assertThat(row).isEmpty();
222-
}
223-
224215
@Test // gh-402
225216
public void writeShouldWritePrimitiveIdIfValueIsNonZero() {
226217

src/test/java/org/springframework/data/r2dbc/core/R2dbcEntityTemplateUnitTests.java

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,46 @@ public void shouldInsertVersioned() {
280280
Parameter.from(1L));
281281
}
282282

283+
@Test // gh-557, gh-402
284+
public void shouldSkipDefaultIdValueOnInsert() {
285+
286+
MockRowMetadata metadata = MockRowMetadata.builder().build();
287+
MockResult result = MockResult.builder().rowMetadata(metadata).rowsUpdated(1).build();
288+
289+
recorder.addStubbing(s -> s.startsWith("INSERT"), result);
290+
291+
entityTemplate.insert(new PersonWithPrimitiveId(0, "bar")).as(StepVerifier::create) //
292+
.expectNextCount(1) //
293+
.verifyComplete();
294+
295+
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("INSERT"));
296+
297+
assertThat(statement.getSql()).isEqualTo("INSERT INTO person_with_primitive_id (name) VALUES ($1)");
298+
assertThat(statement.getBindings()).hasSize(1).containsEntry(0, Parameter.from("bar"));
299+
}
300+
301+
@Test // gh-557, gh-402
302+
public void shouldSkipDefaultIdValueOnVersionedInsert() {
303+
304+
MockRowMetadata metadata = MockRowMetadata.builder().build();
305+
MockResult result = MockResult.builder().rowMetadata(metadata).rowsUpdated(1).build();
306+
307+
recorder.addStubbing(s -> s.startsWith("INSERT"), result);
308+
309+
entityTemplate.insert(new VersionedPersonWithPrimitiveId(0, 0, "bar")).as(StepVerifier::create) //
310+
.assertNext(actual -> {
311+
assertThat(actual.getVersion()).isEqualTo(1);
312+
}) //
313+
.verifyComplete();
314+
315+
StatementRecorder.RecordedStatement statement = recorder.getCreatedStatement(s -> s.startsWith("INSERT"));
316+
317+
assertThat(statement.getSql())
318+
.isEqualTo("INSERT INTO versioned_person_with_primitive_id (version, name) VALUES ($1, $2)");
319+
assertThat(statement.getBindings()).hasSize(2).containsEntry(0, Parameter.from(1L)).containsEntry(1,
320+
Parameter.from("bar"));
321+
}
322+
283323
@Test // gh-451
284324
public void shouldInsertCorrectlyVersionedAndAudited() {
285325

@@ -449,6 +489,26 @@ static class VersionedPerson {
449489
String name;
450490
}
451491

492+
@Value
493+
@With
494+
static class PersonWithPrimitiveId {
495+
496+
@Id int id;
497+
498+
String name;
499+
}
500+
501+
@Value
502+
@With
503+
static class VersionedPersonWithPrimitiveId {
504+
505+
@Id int id;
506+
507+
@Version long version;
508+
509+
String name;
510+
}
511+
452512
@Value
453513
@With
454514
static class WithAuditingAndOptimisticLocking {

0 commit comments

Comments
 (0)