Skip to content

Commit 5a0c5c2

Browse files
committed
DATAJDBC-102 - Moved EntityInstantiator from JdbcMappingContext to DefaultDataAccessStrategy and EntityRowMapper.
1 parent 4260484 commit 5a0c5c2

File tree

12 files changed

+99
-47
lines changed

12 files changed

+99
-47
lines changed

src/main/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategy.java

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.dao.EmptyResultDataAccessException;
2828
import org.springframework.dao.InvalidDataAccessApiUsageException;
2929
import org.springframework.dao.NonTransientDataAccessException;
30+
import org.springframework.data.convert.EntityInstantiators;
3031
import org.springframework.data.jdbc.core.mapping.BasicJdbcPersistentEntityInformation;
3132
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
3233
import org.springframework.data.jdbc.core.mapping.JdbcPersistentEntity;
@@ -58,6 +59,7 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
5859

5960
private final @NonNull SqlGeneratorSource sqlGeneratorSource;
6061
private final @NonNull JdbcMappingContext context;
62+
private final @NonNull EntityInstantiators instantiators;
6163
private final @NonNull DataAccessStrategy accessStrategy;
6264
private final @NonNull NamedParameterJdbcOperations operations;
6365

@@ -66,11 +68,12 @@ public class DefaultDataAccessStrategy implements DataAccessStrategy {
6668
* Only suitable if this is the only access strategy in use.
6769
*/
6870
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context,
69-
NamedParameterJdbcOperations operations) {
71+
EntityInstantiators instantiators, NamedParameterJdbcOperations operations) {
7072

7173
this.sqlGeneratorSource = sqlGeneratorSource;
7274
this.operations = operations;
7375
this.context = context;
76+
this.instantiators = instantiators;
7477
this.accessStrategy = this;
7578
}
7679

@@ -326,7 +329,7 @@ private <S> Optional<Object> getIdFromHolder(KeyHolder holder, JdbcPersistentEnt
326329
}
327330

328331
public <T> EntityRowMapper<T> getEntityRowMapper(Class<T> domainType) {
329-
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), context, accessStrategy);
332+
return new EntityRowMapper<>(getRequiredPersistentEntity(domainType), context, instantiators, accessStrategy);
330333
}
331334

332335
private RowMapper getMapEntityRowMapper(JdbcPersistentProperty property) {

src/main/java/org/springframework/data/jdbc/core/EntityRowMapper.java

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,15 @@ public class EntityRowMapper<T> implements RowMapper<T> {
5353
private final JdbcMappingContext context;
5454
private final DataAccessStrategy accessStrategy;
5555
private final JdbcPersistentProperty idProperty;
56+
private final EntityInstantiators instantiators;
5657

57-
public EntityRowMapper(JdbcPersistentEntity<T> entity, JdbcMappingContext context,
58+
public EntityRowMapper(JdbcPersistentEntity<T> entity, JdbcMappingContext context, EntityInstantiators instantiators,
5859
DataAccessStrategy accessStrategy) {
5960

6061
this.entity = entity;
6162
this.conversions = context.getConversions();
6263
this.context = context;
64+
this.instantiators = instantiators;
6365
this.accessStrategy = accessStrategy;
6466

6567
idProperty = entity.getIdProperty();
@@ -97,7 +99,7 @@ public T mapRow(ResultSet resultSet, int rowNumber) throws SQLException {
9799

98100
private T createInstance(ResultSet rs) {
99101

100-
return context.getInstantiatorFor(entity) //
102+
return instantiators.getInstantiatorFor(entity) //
101103
.createInstance(entity, new ResultSetParameterValueProvider(rs, entity, conversions, ""));
102104
}
103105

@@ -136,7 +138,7 @@ private <S> S readEntityFrom(ResultSet rs, PersistentProperty<?> property) {
136138
return null;
137139
}
138140

139-
S instance = context.getInstantiatorFor(entity) //
141+
S instance = instantiators.getInstantiatorFor(entity) //
140142
.createInstance(entity, new ResultSetParameterValueProvider(rs, entity, conversions, prefix));
141143

142144
PersistentPropertyAccessor accessor = entity.getPropertyAccessor(instance);

src/main/java/org/springframework/data/jdbc/core/mapping/JdbcMappingContext.java

Lines changed: 0 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -27,14 +27,10 @@
2727
import java.util.HashSet;
2828
import java.util.List;
2929

30-
import lombok.Setter;
3130
import org.springframework.core.convert.ConversionService;
3231
import org.springframework.core.convert.support.DefaultConversionService;
3332
import org.springframework.core.convert.support.GenericConversionService;
34-
import org.springframework.data.convert.EntityInstantiator;
35-
import org.springframework.data.convert.EntityInstantiators;
3633
import org.springframework.data.convert.Jsr310Converters;
37-
import org.springframework.data.mapping.PersistentEntity;
3834
import org.springframework.data.mapping.PropertyPath;
3935
import org.springframework.data.mapping.context.AbstractMappingContext;
4036
import org.springframework.data.mapping.context.MappingContext;
@@ -63,8 +59,6 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt
6359
@Getter private final NamingStrategy namingStrategy;
6460
@Getter private SimpleTypeHolder simpleTypeHolder;
6561
private GenericConversionService conversions = getDefaultConversionService();
66-
@Setter
67-
private EntityInstantiators instantiators = new EntityInstantiators();
6862

6963
/**
7064
* Creates a new {@link JdbcMappingContext}.
@@ -150,10 +144,6 @@ public ConversionService getConversions() {
150144
return conversions;
151145
}
152146

153-
public EntityInstantiator getInstantiatorFor(PersistentEntity<?, ?> entity) {
154-
return instantiators.getInstantiatorFor(entity);
155-
}
156-
157147
private static GenericConversionService getDefaultConversionService() {
158148

159149
DefaultConversionService conversionService = new DefaultConversionService();

src/main/java/org/springframework/data/jdbc/mybatis/MyBatisDataAccessStrategy.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222

2323
import org.apache.ibatis.session.SqlSession;
2424
import org.mybatis.spring.SqlSessionTemplate;
25+
import org.springframework.data.convert.EntityInstantiators;
2526
import org.springframework.data.jdbc.core.CascadingDataAccessStrategy;
2627
import org.springframework.data.jdbc.core.DataAccessStrategy;
2728
import org.springframework.data.jdbc.core.DefaultDataAccessStrategy;
@@ -58,15 +59,17 @@ public class MyBatisDataAccessStrategy implements DataAccessStrategy {
5859
*/
5960
public static DataAccessStrategy createCombinedAccessStrategy(JdbcMappingContext context,
6061
NamedParameterJdbcOperations operations, SqlSession sqlSession) {
61-
return createCombinedAccessStrategy(context, operations, sqlSession, NamespaceStrategy.DEFAULT_INSTANCE);
62+
return createCombinedAccessStrategy(context, new EntityInstantiators(), operations, sqlSession,
63+
NamespaceStrategy.DEFAULT_INSTANCE);
6264
}
6365

6466
/**
6567
* Create a {@link DataAccessStrategy} that first checks for queries defined by MyBatis and if it doesn't find one
6668
* uses a {@link DefaultDataAccessStrategy}
6769
*/
6870
public static DataAccessStrategy createCombinedAccessStrategy(JdbcMappingContext context,
69-
NamedParameterJdbcOperations operations, SqlSession sqlSession, NamespaceStrategy namespaceStrategy) {
71+
EntityInstantiators instantiators, NamedParameterJdbcOperations operations, SqlSession sqlSession,
72+
NamespaceStrategy namespaceStrategy) {
7073

7174
// the DefaultDataAccessStrategy needs a reference to the returned DataAccessStrategy. This creates a dependency
7275
// cycle. In order to create it, we need something that allows to defer closing the cycle until all the elements are
@@ -79,8 +82,13 @@ public static DataAccessStrategy createCombinedAccessStrategy(JdbcMappingContext
7982
asList(myBatisDataAccessStrategy, delegatingDataAccessStrategy));
8083

8184
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(context);
82-
DefaultDataAccessStrategy defaultDataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource, context,
83-
cascadingDataAccessStrategy, operations);
85+
DefaultDataAccessStrategy defaultDataAccessStrategy = new DefaultDataAccessStrategy( //
86+
sqlGeneratorSource, //
87+
context, //
88+
instantiators, //
89+
cascadingDataAccessStrategy, //
90+
operations //
91+
);
8492

8593
delegatingDataAccessStrategy.setDelegate(defaultDataAccessStrategy);
8694

@@ -93,7 +101,7 @@ public static DataAccessStrategy createCombinedAccessStrategy(JdbcMappingContext
93101
* Use a {@link SqlSessionTemplate} for {@link SqlSession} or a similar implementation tying the session to the proper
94102
* transaction. Note that the resulting {@link DataAccessStrategy} only handles MyBatis. It does not include the
95103
* functionality of the {@link org.springframework.data.jdbc.core.DefaultDataAccessStrategy} which one normally still
96-
* wants. Use {@link #createCombinedAccessStrategy(JdbcMappingContext, SqlSession)} to create such a
104+
* wants. Use {@link #createCombinedAccessStrategy(JdbcMappingContext, EntityInstantiators, NamedParameterJdbcOperations, SqlSession, NamespaceStrategy)} to create such a
97105
* {@link DataAccessStrategy}.
98106
*
99107
* @param sqlSession Must be non {@literal null}.

src/main/java/org/springframework/data/jdbc/repository/support/JdbcQueryLookupStrategy.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.lang.reflect.Method;
1919

2020
import org.springframework.core.convert.ConversionService;
21+
import org.springframework.data.convert.EntityInstantiators;
2122
import org.springframework.data.jdbc.core.DataAccessStrategy;
2223
import org.springframework.data.jdbc.core.EntityRowMapper;
2324
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
@@ -43,27 +44,30 @@
4344
class JdbcQueryLookupStrategy implements QueryLookupStrategy {
4445

4546
private final JdbcMappingContext context;
47+
private final EntityInstantiators instantiators;
4648
private final DataAccessStrategy accessStrategy;
4749
private final RowMapperMap rowMapperMap;
48-
private final ConversionService conversionService;
4950
private final NamedParameterJdbcOperations operations;
5051

52+
private final ConversionService conversionService;
53+
5154
/**
5255
* Creates a new {@link JdbcQueryLookupStrategy} for the given {@link JdbcMappingContext}, {@link DataAccessStrategy}
5356
* and {@link RowMapperMap}.
54-
*
57+
*
5558
* @param context must not be {@literal null}.
5659
* @param accessStrategy must not be {@literal null}.
5760
* @param rowMapperMap must not be {@literal null}.
5861
*/
59-
JdbcQueryLookupStrategy(JdbcMappingContext context, DataAccessStrategy accessStrategy, RowMapperMap rowMapperMap,
60-
NamedParameterJdbcOperations operations) {
62+
JdbcQueryLookupStrategy(JdbcMappingContext context, EntityInstantiators instantiators,
63+
DataAccessStrategy accessStrategy, RowMapperMap rowMapperMap, NamedParameterJdbcOperations operations) {
6164

6265
Assert.notNull(context, "JdbcMappingContext must not be null!");
6366
Assert.notNull(accessStrategy, "DataAccessStrategy must not be null!");
6467
Assert.notNull(rowMapperMap, "RowMapperMap must not be null!");
6568

6669
this.context = context;
70+
this.instantiators = instantiators;
6771
this.accessStrategy = accessStrategy;
6872
this.rowMapperMap = rowMapperMap;
6973
this.conversionService = context.getConversions();
@@ -104,6 +108,7 @@ private RowMapper<?> determineDefaultRowMapper(JdbcQueryMethod queryMethod) {
104108
? new EntityRowMapper<>( //
105109
context.getRequiredPersistentEntity(domainType), //
106110
context, //
111+
instantiators, //
107112
accessStrategy) //
108113
: typeMappedRowMapper;
109114
}

src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactory.java

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import java.util.Optional;
1919

2020
import org.springframework.context.ApplicationEventPublisher;
21+
import org.springframework.data.convert.EntityInstantiators;
2122
import org.springframework.data.jdbc.core.DataAccessStrategy;
2223
import org.springframework.data.jdbc.core.JdbcAggregateTemplate;
2324
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
@@ -48,6 +49,7 @@ public class JdbcRepositoryFactory extends RepositoryFactorySupport {
4849
private final NamedParameterJdbcOperations operations;
4950

5051
private RowMapperMap rowMapperMap = RowMapperMap.EMPTY;
52+
private EntityInstantiators instantiators = new EntityInstantiators();
5153

5254
/**
5355
* Creates a new {@link JdbcRepositoryFactory} for the given {@link DataAccessStrategy}, {@link JdbcMappingContext}
@@ -81,6 +83,18 @@ public void setRowMapperMap(RowMapperMap rowMapperMap) {
8183
this.rowMapperMap = rowMapperMap;
8284
}
8385

86+
/**
87+
* Set the {@link EntityInstantiators} used for instantiating entity instances.
88+
*
89+
* @param instantiators Must not be {@code null}.
90+
*/
91+
public void setEntityInstantiators(EntityInstantiators instantiators) {
92+
93+
Assert.notNull(instantiators, "EntityInstantiators must not be null.");
94+
95+
this.instantiators = instantiators;
96+
}
97+
8498
@SuppressWarnings("unchecked")
8599
@Override
86100
public <T, ID> EntityInformation<T, ID> getEntityInformation(Class<T> aClass) {
@@ -126,6 +140,6 @@ protected Optional<QueryLookupStrategy> getQueryLookupStrategy(QueryLookupStrate
126140
throw new IllegalArgumentException(String.format("Unsupported query lookup strategy %s!", key));
127141
}
128142

129-
return Optional.of(new JdbcQueryLookupStrategy(context, accessStrategy, rowMapperMap, operations));
143+
return Optional.of(new JdbcQueryLookupStrategy(context, instantiators, accessStrategy, rowMapperMap, operations));
130144
}
131145
}

src/main/java/org/springframework/data/jdbc/repository/support/JdbcRepositoryFactoryBean.java

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020
import org.springframework.beans.factory.annotation.Autowired;
2121
import org.springframework.context.ApplicationEventPublisher;
2222
import org.springframework.context.ApplicationEventPublisherAware;
23+
import org.springframework.data.convert.EntityInstantiators;
2324
import org.springframework.data.jdbc.core.DataAccessStrategy;
2425
import org.springframework.data.jdbc.core.DefaultDataAccessStrategy;
2526
import org.springframework.data.jdbc.core.SqlGeneratorSource;
@@ -49,6 +50,7 @@ public class JdbcRepositoryFactoryBean<T extends Repository<S, ID>, S, ID extend
4950
private DataAccessStrategy dataAccessStrategy;
5051
private RowMapperMap rowMapperMap = RowMapperMap.EMPTY;
5152
private NamedParameterJdbcOperations operations;
53+
private EntityInstantiators instantiators = new EntityInstantiators();
5254

5355
/**
5456
* Creates a new {@link JdbcRepositoryFactoryBean} for the given repository interface.
@@ -115,6 +117,11 @@ public void setJdbcOperations(NamedParameterJdbcOperations operations) {
115117
this.operations = operations;
116118
}
117119

120+
@Autowired(required = false)
121+
public void setInstantiators(EntityInstantiators instantiators) {
122+
this.instantiators = instantiators;
123+
}
124+
118125
/*
119126
* (non-Javadoc)
120127
* @see org.springframework.data.repository.core.support.RepositoryFactoryBeanSupport#afterPropertiesSet()
@@ -127,13 +134,18 @@ public void afterPropertiesSet() {
127134
if (dataAccessStrategy == null) {
128135

129136
SqlGeneratorSource sqlGeneratorSource = new SqlGeneratorSource(mappingContext);
130-
this.dataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource, mappingContext, operations);
137+
this.dataAccessStrategy = new DefaultDataAccessStrategy(sqlGeneratorSource, mappingContext, instantiators,
138+
operations);
131139
}
132140

133141
if (rowMapperMap == null) {
134142
this.rowMapperMap = RowMapperMap.EMPTY;
135143
}
136144

145+
if (instantiators == null) {
146+
this.instantiators = new EntityInstantiators();
147+
}
148+
137149
super.afterPropertiesSet();
138150
}
139151
}

src/test/java/org/springframework/data/jdbc/core/DefaultDataAccessStrategyUnitTests.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
package org.springframework.data.jdbc.core;
1717

1818
import static org.assertj.core.api.Assertions.*;
19-
import static org.mockito.ArgumentMatchers.*;
19+
import static org.mockito.ArgumentMatchers.any;
20+
import static org.mockito.ArgumentMatchers.eq;
2021
import static org.mockito.Mockito.*;
2122

2223
import lombok.RequiredArgsConstructor;
@@ -26,8 +27,8 @@
2627
import org.junit.Test;
2728
import org.mockito.ArgumentCaptor;
2829
import org.springframework.data.annotation.Id;
30+
import org.springframework.data.convert.EntityInstantiators;
2931
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
30-
import org.springframework.data.jdbc.core.mapping.NamingStrategy;
3132
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
3233
import org.springframework.jdbc.core.namedparam.SqlParameterSource;
3334
import org.springframework.jdbc.support.KeyHolder;
@@ -47,8 +48,12 @@ public class DefaultDataAccessStrategyUnitTests {
4748
HashMap<String, Object> additionalParameters = new HashMap<>();
4849
ArgumentCaptor<SqlParameterSource> paramSourceCaptor = ArgumentCaptor.forClass(SqlParameterSource.class);
4950

50-
DefaultDataAccessStrategy accessStrategy = new DefaultDataAccessStrategy(new SqlGeneratorSource(context), context,
51-
jdbcOperations);
51+
DefaultDataAccessStrategy accessStrategy = new DefaultDataAccessStrategy( //
52+
new SqlGeneratorSource(context), //
53+
context, //
54+
new EntityInstantiators(), //
55+
jdbcOperations //
56+
);
5257

5358
@Test // DATAJDBC-146
5459
public void additionalParameterForIdDoesNotLeadToDuplicateParameters() {

src/test/java/org/springframework/data/jdbc/core/EntityRowMapperUnitTests.java

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,8 @@
1717

1818
import static java.util.Arrays.*;
1919
import static org.assertj.core.api.Assertions.*;
20-
import static org.mockito.ArgumentMatchers.*;
20+
import static org.mockito.ArgumentMatchers.any;
21+
import static org.mockito.ArgumentMatchers.eq;
2122
import static org.mockito.Mockito.*;
2223

2324
import lombok.RequiredArgsConstructor;
@@ -40,12 +41,12 @@
4041
import org.springframework.core.convert.support.DefaultConversionService;
4142
import org.springframework.core.convert.support.GenericConversionService;
4243
import org.springframework.data.annotation.Id;
44+
import org.springframework.data.convert.EntityInstantiators;
4345
import org.springframework.data.convert.Jsr310Converters;
4446
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
4547
import org.springframework.data.jdbc.core.mapping.JdbcPersistentEntity;
4648
import org.springframework.data.jdbc.core.mapping.JdbcPersistentProperty;
4749
import org.springframework.data.jdbc.core.mapping.NamingStrategy;
48-
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
4950
import org.springframework.util.Assert;
5051

5152
/**
@@ -199,8 +200,12 @@ private <T> EntityRowMapper<T> createRowMapper(Class<T> type, NamingStrategy nam
199200
DefaultConversionService.addDefaultConverters(conversionService);
200201
Jsr310Converters.getConvertersToRegister().forEach(conversionService::addConverter);
201202

202-
return new EntityRowMapper<>((JdbcPersistentEntity<T>) context.getRequiredPersistentEntity(type), context,
203-
accessStrategy);
203+
return new EntityRowMapper<>( //
204+
(JdbcPersistentEntity<T>) context.getRequiredPersistentEntity(type), //
205+
context, //
206+
new EntityInstantiators(), //
207+
accessStrategy //
208+
);
204209
}
205210

206211
private static ResultSet mockResultSet(List<String> columns, Object... values) {
@@ -212,7 +217,7 @@ private static ResultSet mockResultSet(List<String> columns, Object... values) {
212217
"Number of values [%d] must be a multiple of the number of columns [%d]", //
213218
values.length, //
214219
columns.size() //
215-
) //
220+
) //
216221
);
217222

218223
List<Map<String, Object>> result = convertValues(columns, values);

0 commit comments

Comments
 (0)