diff --git a/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java b/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java index afe9d5ebf..507d42e70 100644 --- a/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java +++ b/src/main/java/org/springframework/data/r2dbc/convert/MappingR2dbcConverter.java @@ -604,13 +604,22 @@ public class MappingR2dbcConverter extends BasicRelationalConverter implements R PersistentPropertyAccessor propertyAccessor = entity.getPropertyAccessor(object); RelationalPersistentProperty idProperty = entity.getRequiredIdProperty(); - if (propertyAccessor.getProperty(idProperty) != null) { - return object; + boolean idPropertyUpdateNeeded = false; + + Object id = propertyAccessor.getProperty(idProperty); + if (idProperty.getType().isPrimitive()) { + idPropertyUpdateNeeded = id instanceof Number && ((Number) id).longValue() == 0; + } else { + idPropertyUpdateNeeded = id == null; } - return potentiallySetId(row, metadata, propertyAccessor, idProperty) // + if (idPropertyUpdateNeeded) { + return potentiallySetId(row, metadata, propertyAccessor, idProperty) // ? (T) propertyAccessor.getBean() // : object; + } + + return object; }; } diff --git a/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java index 156c333c1..446b21b64 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/support/AbstractSimpleR2dbcRepositoryIntegrationTests.java @@ -33,6 +33,7 @@ import javax.sql.DataSource; import org.junit.Before; import org.junit.Test; + import org.springframework.beans.factory.annotation.Autowired; import org.springframework.dao.DataAccessException; import org.springframework.dao.OptimisticLockingFailureException; @@ -105,26 +106,27 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db */ protected abstract String getCreateTableStatement(); - @Test + @Test // gh-444 public void shouldSaveNewObject() { - LegoSet legoSet = new LegoSet(null, "SCHAUFELRADBAGGER", 12); - - repository.save(legoSet) // + repository.save(new LegoSet(0, "SCHAUFELRADBAGGER", 12)) // .as(StepVerifier::create) // .consumeNextWith(actual -> { - assertThat(actual.getId()).isNotNull(); }).verifyComplete(); - Map map = jdbc.queryForMap("SELECT * FROM legoset"); - assertThat(map).containsEntry("name", "SCHAUFELRADBAGGER").containsEntry("manual", 12).containsKey("id"); + repository.save(new LegoSet(0, "SCHAUFELRADBAGGER", 12)) // + .as(StepVerifier::create) // + .consumeNextWith(actual -> { + + assertThat(actual.getId()).isGreaterThan(0); + }).verifyComplete(); } @Test // gh-93 public void shouldSaveNewObjectAndSetVersionIfWrapperVersionPropertyExists() { - LegoSetVersionable legoSet = new LegoSetVersionable(null, "SCHAUFELRADBAGGER", 12, null); + LegoSetVersionable legoSet = new LegoSetVersionable(0, "SCHAUFELRADBAGGER", 12, null); repository.save(legoSet) // .as(StepVerifier::create) // @@ -142,7 +144,7 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db @Test // gh-93 public void shouldSaveNewObjectAndSetVersionIfPrimitiveVersionPropertyExists() { - LegoSetPrimitiveVersionable legoSet = new LegoSetPrimitiveVersionable(null, "SCHAUFELRADBAGGER", 12, 0); + LegoSetPrimitiveVersionable legoSet = new LegoSetPrimitiveVersionable(0, "SCHAUFELRADBAGGER", 12, 0); repository.save(legoSet) // .as(StepVerifier::create) // @@ -216,10 +218,10 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db @Test public void shouldSaveObjectsUsingIterable() { - LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12); - LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13); - LegoSet legoSet3 = new LegoSet(null, "RALLYEAUTO", 14); - LegoSet legoSet4 = new LegoSet(null, "VOLTRON", 15); + LegoSet legoSet1 = new LegoSet(0, "SCHAUFELRADBAGGER", 12); + LegoSet legoSet2 = new LegoSet(0, "FORSCHUNGSSCHIFF", 13); + LegoSet legoSet3 = new LegoSet(0, "RALLYEAUTO", 14); + LegoSet legoSet4 = new LegoSet(0, "VOLTRON", 15); repository.saveAll(Arrays.asList(legoSet1, legoSet2, legoSet3, legoSet4)) // .map(LegoSet::getManual) // @@ -237,8 +239,8 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db @Test public void shouldSaveObjectsUsingPublisher() { - LegoSet legoSet1 = new LegoSet(null, "SCHAUFELRADBAGGER", 12); - LegoSet legoSet2 = new LegoSet(null, "FORSCHUNGSSCHIFF", 13); + LegoSet legoSet1 = new LegoSet(0, "SCHAUFELRADBAGGER", 12); + LegoSet legoSet2 = new LegoSet(0, "FORSCHUNGSSCHIFF", 13); repository.saveAll(Flux.just(legoSet1, legoSet2)) // .as(StepVerifier::create) // @@ -468,27 +470,11 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db @Table("legoset") @AllArgsConstructor @NoArgsConstructor - static class LegoSet implements Persistable { - @Id Integer id; + static class LegoSet { + @Id int id; String name; Integer manual; - @Override - public boolean isNew() { - return id == null; - } - } - - static class AlwaysNewLegoSet extends LegoSet { - - AlwaysNewLegoSet(Integer id, String name, Integer manual) { - super(id, name, manual); - } - - @Override - public boolean isNew() { - return true; - } } @Data @@ -497,7 +483,7 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db static class LegoSetVersionable extends LegoSet { @Version Integer version; - public LegoSetVersionable(Integer id, String name, Integer manual, Integer version) { + public LegoSetVersionable(int id, String name, Integer manual, Integer version) { super(id, name, manual); this.version = version; } @@ -509,7 +495,7 @@ public abstract class AbstractSimpleR2dbcRepositoryIntegrationTests extends R2db static class LegoSetPrimitiveVersionable extends LegoSet { @Version int version; - public LegoSetPrimitiveVersionable(Integer id, String name, Integer manual, int version) { + public LegoSetPrimitiveVersionable(int id, String name, Integer manual, int version) { super(id, name, manual); this.version = version; } diff --git a/src/test/java/org/springframework/data/r2dbc/repository/support/H2SimpleR2dbcRepositoryIntegrationTests.java b/src/test/java/org/springframework/data/r2dbc/repository/support/H2SimpleR2dbcRepositoryIntegrationTests.java index 31751b8e7..228a624e3 100644 --- a/src/test/java/org/springframework/data/r2dbc/repository/support/H2SimpleR2dbcRepositoryIntegrationTests.java +++ b/src/test/java/org/springframework/data/r2dbc/repository/support/H2SimpleR2dbcRepositoryIntegrationTests.java @@ -18,6 +18,8 @@ package org.springframework.data.r2dbc.repository.support; import static org.assertj.core.api.Assertions.*; import io.r2dbc.spi.ConnectionFactory; +import lombok.AllArgsConstructor; +import lombok.Data; import reactor.test.StepVerifier; import java.util.Map; @@ -27,11 +29,19 @@ import javax.sql.DataSource; import org.junit.Test; import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Configuration; import org.springframework.dao.DataAccessException; import org.springframework.dao.TransientDataAccessException; +import org.springframework.data.annotation.Id; +import org.springframework.data.domain.Persistable; import org.springframework.data.r2dbc.config.AbstractR2dbcConfiguration; +import org.springframework.data.r2dbc.core.R2dbcEntityTemplate; import org.springframework.data.r2dbc.testing.H2TestSupport; +import org.springframework.data.relational.core.mapping.RelationalMappingContext; +import org.springframework.data.relational.core.mapping.RelationalPersistentEntity; +import org.springframework.data.relational.repository.query.RelationalEntityInformation; +import org.springframework.data.relational.repository.support.MappingRelationalEntityInformation; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; @@ -44,6 +54,10 @@ import org.springframework.test.context.junit4.SpringRunner; @ContextConfiguration public class H2SimpleR2dbcRepositoryIntegrationTests extends AbstractSimpleR2dbcRepositoryIntegrationTests { + @Autowired private R2dbcEntityTemplate entityTemplate; + + @Autowired private RelationalMappingContext mappingContext; + @Configuration static class IntegrationTestConfiguration extends AbstractR2dbcConfiguration { @@ -67,21 +81,30 @@ public class H2SimpleR2dbcRepositoryIntegrationTests extends AbstractSimpleR2dbc public void shouldInsertNewObjectWithGivenId() { try { - this.jdbc.execute("DROP TABLE legoset"); + this.jdbc.execute("DROP TABLE always_new"); } catch (DataAccessException e) {} - this.jdbc.execute(H2TestSupport.CREATE_TABLE_LEGOSET); + this.jdbc.execute("CREATE TABLE always_new (\n" // + + " id integer PRIMARY KEY,\n" // + + " name varchar(255) NOT NULL" // + + ");"); - AlwaysNewLegoSet legoSet = new AlwaysNewLegoSet(9999, "SCHAUFELRADBAGGER", 12); + RelationalEntityInformation entityInformation = new MappingRelationalEntityInformation<>( + (RelationalPersistentEntity) mappingContext.getRequiredPersistentEntity(AlwaysNew.class)); - repository.save(legoSet) // + SimpleR2dbcRepository repository = new SimpleR2dbcRepository<>(entityInformation, entityTemplate, + entityTemplate.getConverter()); + + AlwaysNew alwaysNew = new AlwaysNew(9999L, "SCHAUFELRADBAGGER"); + + repository.save(alwaysNew) // .as(StepVerifier::create) // .consumeNextWith( // actual -> assertThat(actual.getId()).isEqualTo(9999) // ).verifyComplete(); - Map map = jdbc.queryForMap("SELECT * FROM legoset"); - assertThat(map).containsEntry("name", "SCHAUFELRADBAGGER").containsEntry("manual", 12).containsKey("id"); + Map map = jdbc.queryForMap("SELECT * FROM always_new"); + assertThat(map).containsEntry("name", "SCHAUFELRADBAGGER").containsKey("id"); } @Test // gh-232 @@ -97,4 +120,17 @@ public class H2SimpleR2dbcRepositoryIntegrationTests extends AbstractSimpleR2dbc .hasMessage("Failed to update table [legoset]. Row with Id [9999] does not exist."); }); } + + @Data + @AllArgsConstructor + static class AlwaysNew implements Persistable { + + @Id Long id; + String name; + + @Override + public boolean isNew() { + return true; + } + } }