diff --git a/pom.xml b/pom.xml index 634c3fe1f5..59723e79bf 100644 --- a/pom.xml +++ b/pom.xml @@ -5,7 +5,7 @@ org.springframework.data spring-data-jdbc - 1.0.0.BUILD-SNAPSHOT + 1.0.0.DATAJDBC-181-SNAPSHOT Spring Data JDBC Spring Data module for JDBC repositories. 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 cf01f151ff..73b28b155d 100644 --- a/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java +++ b/src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java @@ -16,6 +16,7 @@ package org.springframework.data.jdbc.core; import lombok.NonNull; +import lombok.RequiredArgsConstructor; import org.springframework.core.convert.ConversionService; import org.springframework.core.convert.converter.Converter; import org.springframework.data.convert.ClassGeneratingEntityInstantiator; @@ -94,7 +95,7 @@ public T mapRow(ResultSet resultSet, int rowNumber) throws SQLException { } private T createInstance(ResultSet rs) { - return instantiator.createInstance(entity, ResultSetParameterValueProvider.of(rs, conversions, "")); + return instantiator.createInstance(entity, new ResultSetParameterValueProvider(rs, entity, conversions, "")); } private Object readFrom(ResultSet resultSet, JdbcPersistentProperty property, String prefix) { @@ -123,7 +124,7 @@ private S readEntityFrom(ResultSet rs, PersistentProperty property) { return null; } - S instance = instantiator.createInstance(entity, ResultSetParameterValueProvider.of(rs, conversions, prefix)); + S instance = instantiator.createInstance(entity, new ResultSetParameterValueProvider(rs, entity, conversions, prefix)); PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance); ConvertingPropertyAccessor propertyAccessor = new ConvertingPropertyAccessor(accessor, conversions); @@ -135,27 +136,18 @@ private S readEntityFrom(ResultSet rs, PersistentProperty property) { return instance; } + @RequiredArgsConstructor private static class ResultSetParameterValueProvider implements ParameterValueProvider { @NonNull private final ResultSet resultSet; @NonNull + private final JdbcPersistentEntity entity; + @NonNull private final ConversionService conversionService; @NonNull private final String prefix; - private ResultSetParameterValueProvider(ResultSet resultSet, ConversionService conversionService, String prefix) { - - this.resultSet = resultSet; - this.conversionService = conversionService; - this.prefix = prefix; - } - - public static ResultSetParameterValueProvider of(ResultSet resultSet, ConversionService conversionService, - String prefix) { - return new ResultSetParameterValueProvider(resultSet, conversionService, prefix); - } - /* * (non-Javadoc) * @see org.springframework.data.mapping.model.ParameterValueProvider#getParameterValue(org.springframework.data.mapping.PreferredConstructor.Parameter) @@ -163,12 +155,8 @@ public static ResultSetParameterValueProvider of(ResultSet resultSet, Conversion @Override public T getParameterValue(Parameter parameter) { - String name = parameter.getName(); - if (name == null) { - return null; - } + String column = prefix + entity.getRequiredPersistentProperty(parameter.getName()).getColumnName(); - String column = prefix + name; try { return conversionService.convert(resultSet.getObject(column), parameter.getType().getType()); } catch (SQLException o_O) { 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 d1ecbe146b..36798f02e5 100644 --- a/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java +++ b/src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java @@ -23,9 +23,12 @@ import org.springframework.core.convert.support.GenericConversionService; import org.springframework.data.annotation.Id; import org.springframework.data.convert.Jsr310Converters; +import org.springframework.data.jdbc.mapping.model.DefaultNamingStrategy; import org.springframework.data.jdbc.mapping.model.JdbcMappingContext; import org.springframework.data.jdbc.mapping.model.JdbcPersistentEntity; import org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty; +import org.springframework.data.jdbc.mapping.model.NamingStrategy; +import org.springframework.data.repository.query.Param; import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations; import org.springframework.util.Assert; @@ -54,6 +57,12 @@ public class EntityRowMapperUnitTests { public static final long ID_FOR_ENTITY_REFERENCING_MAP = 42L; public static final long ID_FOR_ENTITY_REFERENCING_LIST = 4711L; public static final long ID_FOR_ENTITY_NOT_REFERENCING_MAP = 23L; + public static final DefaultNamingStrategy X_APPENDING_NAMINGSTRATEGY = new DefaultNamingStrategy() { + @Override + public String getColumnName(JdbcPersistentProperty property) { + return super.getColumnName(property) + "x"; + } + }; @Test // DATAJDBC-113 public void simpleEntitiesGetProperlyExtracted() throws SQLException { @@ -70,6 +79,36 @@ public void simpleEntitiesGetProperlyExtracted() throws SQLException { .containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha"); } + @Test // DATAJDBC-181 + public void namingStrategyGetsHonored() throws SQLException { + + ResultSet rs = mockResultSet(asList("idx", "namex"), // + ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha"); + rs.next(); + + Trivial extracted = createRowMapper(Trivial.class, X_APPENDING_NAMINGSTRATEGY).mapRow(rs, 1); + + assertThat(extracted) // + .isNotNull() // + .extracting(e -> e.id, e -> e.name) // + .containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha"); + } + + @Test // DATAJDBC-181 + public void namingStrategyGetsHonoredForConstructor() throws SQLException { + + ResultSet rs = mockResultSet(asList("idx", "namex"), // + ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha"); + rs.next(); + + TrivialImmutable extracted = createRowMapper(TrivialImmutable.class, X_APPENDING_NAMINGSTRATEGY).mapRow(rs, 1); + + assertThat(extracted) // + .isNotNull() // + .extracting(e -> e.id, e -> e.name) // + .containsExactly(ID_FOR_ENTITY_NOT_REFERENCING_MAP, "alpha"); + } + @Test // DATAJDBC-113 public void simpleOneToOneGetsProperlyExtracted() throws SQLException { @@ -131,8 +170,18 @@ public void listReferenceGetsLoadedWithAdditionalSelect() throws SQLException { } private EntityRowMapper createRowMapper(Class type) { + return createRowMapper(type, new DefaultNamingStrategy()); + } + + private EntityRowMapper createRowMapper(Class type, NamingStrategy namingStrategy) { + + JdbcMappingContext context = new JdbcMappingContext( // + namingStrategy, // + mock(NamedParameterJdbcOperations.class), // + __ -> { + } // + ); - JdbcMappingContext context = new JdbcMappingContext(mock(NamedParameterJdbcOperations.class)); DataAccessStrategy accessStrategy = mock(DataAccessStrategy.class); // the ID of the entity is used to determine what kind of ResultSet is needed for subsequent selects. @@ -240,7 +289,12 @@ private boolean isBeforeFirst() { } private Object getObject(String column) { - return values.get(index).get(column); + + Map rowMap = values.get(index); + + Assert.isTrue(rowMap.containsKey(column), String.format("Trying to access a column (%s) that does not exist", column)); + + return rowMap.get(column); } private boolean next() { @@ -251,6 +305,13 @@ private boolean next() { } @RequiredArgsConstructor + static class TrivialImmutable { + + @Id + private final Long id; + private final String name; + } + static class Trivial { @Id @@ -258,7 +319,6 @@ static class Trivial { String name; } - @RequiredArgsConstructor static class OneToOne { @Id @@ -267,7 +327,6 @@ static class OneToOne { Trivial child; } - @RequiredArgsConstructor static class OneToSet { @Id @@ -276,7 +335,6 @@ static class OneToSet { Set children; } - @RequiredArgsConstructor static class OneToMap { @Id @@ -285,7 +343,6 @@ static class OneToMap { Map children; } - @RequiredArgsConstructor static class OneToList { @Id