From baeb8d84ab0a31b8c4dc32399f8f4976267dcca5 Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Sat, 13 Oct 2018 07:47:14 +0200 Subject: [PATCH 1/2] DATAJDBC-273 - Prepare branch. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index deedf29b73..6ec3b55f0a 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ org.springframework.data spring-data-jdbc - 1.1.0.BUILD-SNAPSHOT + 1.1.0.DATAJDBC-273-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. From aec57220276ad334995a708bf5fc1be6b4164b0d Mon Sep 17 00:00:00 2001 From: Jens Schauder Date: Mon, 15 Oct 2018 16:12:21 +0200 Subject: [PATCH 2/2] DATAJDBC-273 - Added support for collections and similar in constructors of entities. Instance creation now uses the same code for materializing property values as the part setting properties. --- .../data/jdbc/core/EntityRowMapper.java | 54 ++++++++++++------- .../jdbc/core/EntityRowMapperUnitTests.java | 30 +++++++++-- 2 files changed, 60 insertions(+), 24 deletions(-) diff --git a/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java b/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java index f6fefd5498..2ea9327d1b 100644 --- a/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java +++ b/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java @@ -67,7 +67,16 @@ public EntityRowMapper(RelationalPersistentEntity entity, RelationalMappingCo @Override public T mapRow(ResultSet resultSet, int rowNumber) { - T result = createInstance(entity, resultSet, ""); + String prefix = ""; + + RelationalPersistentProperty idProperty = entity.getIdProperty(); + + Object idValue = null; + if (idProperty != null) { + idValue = readFrom(resultSet, idProperty, prefix); + } + + T result = createInstance(entity, resultSet, idValue); return entity.requiresPropertyPopulation() // ? populateProperties(result, resultSet) // @@ -88,26 +97,24 @@ private T populateProperties(T result, ResultSet resultSet) { continue; } - if (property.isCollectionLike() && id != null) { - - propertyAccessor.setProperty(property, accessStrategy.findAllByProperty(id, property)); - - } else if (property.isMap() && id != null) { - - Iterable allByProperty = accessStrategy.findAllByProperty(id, property); - propertyAccessor.setProperty(property, ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(allByProperty)); - - } else { - - final Object value = readFrom(resultSet, property, ""); - - propertyAccessor.setProperty(property, value); - } + propertyAccessor.setProperty(property, readOrLoadProperty(resultSet, id, property)); } return propertyAccessor.getBean(); } + @Nullable + private Object readOrLoadProperty(ResultSet resultSet, @Nullable Object id, RelationalPersistentProperty property) { + + if (property.isCollectionLike() && id != null) { + return accessStrategy.findAllByProperty(id, property); + } else if (property.isMap() && id != null) { + return ITERABLE_OF_ENTRY_TO_MAP_CONVERTER.convert(accessStrategy.findAllByProperty(id, property)); + } else { + return readFrom(resultSet, property, ""); + } + } + /** * Read a single value or a complete Entity from the {@link ResultSet} passed as an argument. * @@ -139,14 +146,20 @@ private S readEntityFrom(ResultSet rs, RelationalPersistentProperty property RelationalPersistentProperty idProperty = entity.getIdProperty(); + Object idValue = null; + + if (idProperty != null) { + idValue = readFrom(rs, idProperty, prefix); + } + if ((idProperty != null // - ? readFrom(rs, idProperty, prefix) // + ? idValue // : getObjectFromResultSet(rs, prefix + property.getReverseColumnName()) // ) == null) { return null; } - S instance = createInstance(entity, rs, prefix); + S instance = createInstance(entity, rs, idValue); PersistentPropertyAccessor accessor = converter.getPropertyAccessor(entity, instance); @@ -167,7 +180,7 @@ private Object getObjectFromResultSet(ResultSet rs, String backreferenceName) { } } - private S createInstance(RelationalPersistentEntity entity, ResultSet rs, String prefix) { + private S createInstance(RelationalPersistentEntity entity, ResultSet rs, @Nullable Object idValue) { return converter.createInstance(entity, parameter -> { @@ -176,7 +189,8 @@ private S createInstance(RelationalPersistentEntity entity, ResultSet rs, Assert.notNull(parameterName, "A constructor parameter name must not be null to be used with Spring Data JDBC"); RelationalPersistentProperty property = entity.getRequiredPersistentProperty(parameterName); - return readFrom(rs, property, prefix); + + return readOrLoadProperty(rs, idValue, property); }); } } diff --git a/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java b/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java index b1bfb3efd2..51a9c30121 100644 --- a/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java @@ -21,6 +21,7 @@ import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.*; +import lombok.AllArgsConstructor; import lombok.RequiredArgsConstructor; import lombok.experimental.Wither; @@ -201,6 +202,18 @@ public void handlesMixedProperties() throws SQLException { .isEqualTo(new String[] { "111", "222", "333" }); } + @Test // DATAJDBC-273 + public void handlesNonSimplePropertyInConstructor() throws SQLException { + + ResultSet rs = mockResultSet(asList("id"), // + ID_FOR_ENTITY_REFERENCING_LIST); + rs.next(); + + EntityWithListInConstructor extracted = createRowMapper(EntityWithListInConstructor.class).mapRow(rs, 1); + + assertThat(extracted.content).hasSize(2); + } + private EntityRowMapper createRowMapper(Class type) { return createRowMapper(type, NamingStrategy.INSTANCE); } @@ -246,7 +259,7 @@ private static ResultSet mockResultSet(List columns, Object... values) { "Number of values [%d] must be a multiple of the number of columns [%d]", // values.length, // columns.size() // - ) // + ) // ); List> result = convertValues(columns, values); @@ -318,12 +331,13 @@ private boolean isBeforeFirst() { return index < 0 && !values.isEmpty(); } - private Object getObject(String column) { + private Object getObject(String column) throws SQLException { Map rowMap = values.get(index); - Assert.isTrue(rowMap.containsKey(column), - String.format("Trying to access a column (%s) that does not exist", column)); + if (!rowMap.containsKey(column)) { + throw new SQLException(String.format("Trying to access a column (%s) that does not exist", column)); + } return rowMap.get(column); } @@ -408,4 +422,12 @@ MixedProperties withThree(String three) { return new MixedProperties(one, two, three); } } + + @AllArgsConstructor + static class EntityWithListInConstructor { + + @Id final Long id; + + final List content; + } }