DATAJDBC-181 - Use NamingStrategy for instantiating entities.
The ResultSetParameterValueProvider uses the relevant property for a requested parameter in order to obtain the proper column name to use. Improved mocking of ResultSets in tests to actually fail when a non existing column gets requested instead of just returning null.
This commit is contained in:
committed by
Greg Turnquist
parent
043bd4de35
commit
18bf6ca77c
@@ -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 class EntityRowMapper<T> implements RowMapper<T> {
|
||||
}
|
||||
|
||||
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 @@ public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
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 @@ public class EntityRowMapper<T> implements RowMapper<T> {
|
||||
return instance;
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
private static class ResultSetParameterValueProvider implements ParameterValueProvider<JdbcPersistentProperty> {
|
||||
|
||||
@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 class EntityRowMapper<T> implements RowMapper<T> {
|
||||
@Override
|
||||
public <T> T getParameterValue(Parameter<T, JdbcPersistentProperty> 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) {
|
||||
|
||||
@@ -23,9 +23,12 @@ import org.springframework.core.convert.support.DefaultConversionService;
|
||||
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 class EntityRowMapperUnitTests {
|
||||
.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 class EntityRowMapperUnitTests {
|
||||
}
|
||||
|
||||
private <T> EntityRowMapper<T> createRowMapper(Class<T> type) {
|
||||
return createRowMapper(type, new DefaultNamingStrategy());
|
||||
}
|
||||
|
||||
private <T> EntityRowMapper<T> createRowMapper(Class<T> 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 @@ public class EntityRowMapperUnitTests {
|
||||
}
|
||||
|
||||
private Object getObject(String column) {
|
||||
return values.get(index).get(column);
|
||||
|
||||
Map<String, Object> 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 @@ public class EntityRowMapperUnitTests {
|
||||
}
|
||||
|
||||
@RequiredArgsConstructor
|
||||
static class TrivialImmutable {
|
||||
|
||||
@Id
|
||||
private final Long id;
|
||||
private final String name;
|
||||
}
|
||||
|
||||
static class Trivial {
|
||||
|
||||
@Id
|
||||
|
||||
Reference in New Issue
Block a user