Skip to content

Commit d0a8af2

Browse files
committed
DATAJDBC-137 - Polishing.
Moved the dependency to NamedParameterJdbcOperations out of JdbcMappingContext. This revealed that despite the DataAccessStrategy abstraction, there are a couple of places in the query execution subsystem that work with a plain NamedParameterJdbcOperations instance, so that we now have to carry that around all the way from the repository factory bean. Improving that is subject for further changes. A bit of JavaDoc and generics polish here and there.
1 parent fbc271a commit d0a8af2

34 files changed

+254
-253
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,8 @@
2121
import org.springframework.data.mapping.PropertyPath;
2222

2323
/**
24-
* Abstraction for accesses to the database that should be implementable with a single SQL statement and relates to a single entity as opposed to {@link JdbcEntityOperations} which provides interactions related to complete aggregates.
24+
* Abstraction for accesses to the database that should be implementable with a single SQL statement and relates to a
25+
* single entity as opposed to {@link JdbcEntityOperations} which provides interactions related to complete aggregates.
2526
*
2627
* @author Jens Schauder
2728
* @since 1.0
@@ -68,5 +69,4 @@ public interface DataAccessStrategy {
6869
<T> Iterable<T> findAllByProperty(Object rootId, JdbcPersistentProperty property);
6970

7071
<T> boolean existsById(Object id, Class<T> domainType);
71-
7272
}

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

Lines changed: 60 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@
1515
*/
1616
package org.springframework.data.jdbc.core;
1717

18+
import lombok.NonNull;
19+
import lombok.RequiredArgsConstructor;
20+
1821
import java.util.HashMap;
1922
import java.util.Map;
2023
import java.util.Optional;
@@ -46,34 +49,27 @@
4649
* @author Jens Schauder
4750
* @since 1.0
4851
*/
52+
@RequiredArgsConstructor
4953
public class DefaultDataAccessStrategy implements DataAccessStrategy {
5054

5155
private static final String ENTITY_NEW_AFTER_INSERT = "Entity [%s] still 'new' after insert. Please set either"
5256
+ " the id property in a BeforeInsert event handler, or ensure the database creates a value and your "
5357
+ "JDBC driver returns it.";
5458

55-
private final SqlGeneratorSource sqlGeneratorSource;
56-
private final NamedParameterJdbcOperations operations;
57-
private final JdbcMappingContext context;
58-
private final DataAccessStrategy accessStrategy;
59-
60-
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context,
61-
DataAccessStrategy accessStrategy) {
62-
63-
this.sqlGeneratorSource = sqlGeneratorSource;
64-
this.operations = context.getTemplate();
65-
this.context = context;
66-
this.accessStrategy = accessStrategy;
67-
}
59+
private final @NonNull SqlGeneratorSource sqlGeneratorSource;
60+
private final @NonNull JdbcMappingContext context;
61+
private final @NonNull DataAccessStrategy accessStrategy;
62+
private final @NonNull NamedParameterJdbcOperations operations;
6863

6964
/**
7065
* Creates a {@link DefaultDataAccessStrategy} which references it self for resolution of recursive data accesses.
7166
* Only suitable if this is the only access strategy in use.
7267
*/
73-
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context) {
68+
public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, JdbcMappingContext context,
69+
NamedParameterJdbcOperations operations) {
7470

7571
this.sqlGeneratorSource = sqlGeneratorSource;
76-
this.operations = context.getTemplate();
72+
this.operations = operations;
7773
this.context = context;
7874
this.accessStrategy = this;
7975
}
@@ -110,9 +106,12 @@ public <T> void insert(T instance, Class<T> domainType, Map<String, Object> addi
110106
if (idProperty != null && idValue == null && entityInformation.isNew(instance)) {
111107
throw new IllegalStateException(String.format(ENTITY_NEW_AFTER_INSERT, persistentEntity));
112108
}
113-
114109
}
115110

111+
/*
112+
* (non-Javadoc)
113+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class)
114+
*/
116115
@Override
117116
public <S> void update(S instance, Class<S> domainType) {
118117

@@ -121,6 +120,10 @@ public <S> void update(S instance, Class<S> domainType) {
121120
operations.update(sql(domainType).getUpdate(), getPropertyMap(instance, persistentEntity));
122121
}
123122

123+
/*
124+
* (non-Javadoc)
125+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class)
126+
*/
124127
@Override
125128
public void delete(Object id, Class<?> domainType) {
126129

@@ -130,6 +133,10 @@ public void delete(Object id, Class<?> domainType) {
130133
operations.update(deleteByIdSql, parameter);
131134
}
132135

136+
/*
137+
* (non-Javadoc)
138+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PropertyPath)
139+
*/
133140
@Override
134141
public void delete(Object rootId, PropertyPath propertyPath) {
135142

@@ -145,39 +152,63 @@ public void delete(Object rootId, PropertyPath propertyPath) {
145152
operations.update(format, parameters);
146153
}
147154

155+
/*
156+
* (non-Javadoc)
157+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class)
158+
*/
148159
@Override
149160
public <T> void deleteAll(Class<T> domainType) {
150161
operations.getJdbcOperations().update(sql(domainType).createDeleteAllSql(null));
151162
}
152163

164+
/*
165+
* (non-Javadoc)
166+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PropertyPath)
167+
*/
153168
@Override
154169
public <T> void deleteAll(PropertyPath propertyPath) {
155170
operations.getJdbcOperations().update(sql(propertyPath.getOwningType().getType()).createDeleteAllSql(propertyPath));
156171
}
157172

158-
@SuppressWarnings("ConstantConditions")
173+
/*
174+
* (non-Javadoc)
175+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class)
176+
*/
159177
@Override
160178
public long count(Class<?> domainType) {
161179
return operations.getJdbcOperations().queryForObject(sql(domainType).getCount(), Long.class);
162180
}
163181

182+
/*
183+
* (non-Javadoc)
184+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class)
185+
*/
164186
@Override
165187
public <T> T findById(Object id, Class<T> domainType) {
166188

167189
String findOneSql = sql(domainType).getFindOne();
168190
MapSqlParameterSource parameter = createIdParameterSource(id, domainType);
191+
169192
try {
170193
return operations.queryForObject(findOneSql, parameter, getEntityRowMapper(domainType));
171194
} catch (EmptyResultDataAccessException e) {
172195
return null;
173196
}
174197
}
175198

199+
/*
200+
* (non-Javadoc)
201+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class)
202+
*/
176203
@Override
177204
public <T> Iterable<T> findAll(Class<T> domainType) {
178205
return operations.query(sql(domainType).getFindAll(), getEntityRowMapper(domainType));
179206
}
180207

208+
/*
209+
* (non-Javadoc)
210+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class)
211+
*/
181212
@Override
182213
public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
183214

@@ -194,15 +225,19 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
194225
return operations.query(findAllInListSql, parameter, getEntityRowMapper(domainType));
195226
}
196227

197-
@SuppressWarnings("unchecked")
228+
/*
229+
* (non-Javadoc)
230+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.jdbc.mapping.model.JdbcPersistentProperty)
231+
*/
198232
@Override
233+
@SuppressWarnings("unchecked")
199234
public <T> Iterable<T> findAllByProperty(Object rootId, JdbcPersistentProperty property) {
200235

201236
Assert.notNull(rootId, "rootId must not be null.");
202237

203238
Class<?> actualType = property.getActualType();
204-
String findAllByProperty = sql(actualType).getFindAllByProperty(property.getReverseColumnName(),
205-
property.getKeyColumn(), property.isOrdered());
239+
String findAllByProperty = sql(actualType) //
240+
.getFindAllByProperty(property.getReverseColumnName(), property.getKeyColumn(), property.isOrdered());
206241

207242
MapSqlParameterSource parameter = new MapSqlParameterSource(property.getReverseColumnName(), rootId);
208243

@@ -211,11 +246,16 @@ public <T> Iterable<T> findAllByProperty(Object rootId, JdbcPersistentProperty p
211246
: getEntityRowMapper(actualType));
212247
}
213248

249+
/*
250+
* (non-Javadoc)
251+
* @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class)
252+
*/
214253
@Override
215254
public <T> boolean existsById(Object id, Class<T> domainType) {
216255

217256
String existsSql = sql(domainType).getExists();
218257
MapSqlParameterSource parameter = createIdParameterSource(id, domainType);
258+
219259
return operations.queryForObject(existsSql, parameter, Boolean.class);
220260
}
221261

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

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@
2020

2121
import java.sql.ResultSet;
2222
import java.sql.SQLException;
23+
import java.util.Map;
2324

2425
import org.springframework.core.convert.ConversionService;
2526
import org.springframework.core.convert.converter.Converter;
@@ -35,8 +36,6 @@
3536
import org.springframework.data.mapping.model.ConvertingPropertyAccessor;
3637
import org.springframework.data.mapping.model.ParameterValueProvider;
3738
import org.springframework.jdbc.core.RowMapper;
38-
import org.springframework.lang.Nullable;
39-
import org.springframework.util.Assert;
4039

4140
/**
4241
* Maps a ResultSet to an entity of type {@code T}, including entities referenced.
@@ -47,7 +46,7 @@
4746
*/
4847
public class EntityRowMapper<T> implements RowMapper<T> {
4948

50-
private static final Converter ITERABLE_OF_ENTRY_TO_MAP_CONVERTER = new IterableOfEntryToMapConverter();
49+
private static final Converter<Iterable<?>, Map<?, ?>> ITERABLE_OF_ENTRY_TO_MAP_CONVERTER = new IterableOfEntryToMapConverter();
5150

5251
private final JdbcPersistentEntity<T> entity;
5352
private final EntityInstantiator instantiator = new ClassGeneratingEntityInstantiator();
@@ -101,14 +100,12 @@ private T createInstance(ResultSet rs) {
101100
return instantiator.createInstance(entity, new ResultSetParameterValueProvider(rs, entity, conversions, ""));
102101
}
103102

104-
105103
/**
106104
* Read a single value or a complete Entity from the {@link ResultSet} passed as an argument.
107105
*
108106
* @param resultSet the {@link ResultSet} to extract the value from. Must not be {@code null}.
109107
* @param property the {@link JdbcPersistentProperty} for which the value is intended. Must not be {@code null}.
110108
* @param prefix to be used for all column names accessed by this method. Must not be {@code null}.
111-
*
112109
* @return the value read from the {@link ResultSet}. May be {@code null}.
113110
*/
114111
private Object readFrom(ResultSet resultSet, JdbcPersistentProperty property, String prefix) {

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

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,27 +15,27 @@
1515
*/
1616
package org.springframework.data.jdbc.core;
1717

18+
import java.util.HashMap;
19+
import java.util.Map;
20+
import java.util.Map.Entry;
21+
1822
import org.springframework.core.convert.TypeDescriptor;
1923
import org.springframework.core.convert.converter.ConditionalConverter;
2024
import org.springframework.core.convert.converter.Converter;
2125
import org.springframework.lang.Nullable;
2226
import org.springframework.util.Assert;
2327

24-
import java.util.HashMap;
25-
import java.util.Map;
26-
import java.util.Map.Entry;
27-
2828
/**
2929
* A converter for creating a {@link Map} from an {@link Iterable<Map.Entry>}.
3030
*
3131
* @author Jens Schauder
3232
* @since 1.0
3333
*/
34-
class IterableOfEntryToMapConverter implements ConditionalConverter, Converter<Iterable, Map> {
34+
class IterableOfEntryToMapConverter implements ConditionalConverter, Converter<Iterable<?>, Map<?, ?>> {
3535

3636
@Nullable
3737
@Override
38-
public Map convert(Iterable source) {
38+
public Map<?, ?> convert(Iterable<?> source) {
3939

4040
Map result = new HashMap();
4141

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

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,5 +40,4 @@ public interface JdbcEntityOperations {
4040
<T> Iterable<T> findAll(Class<T> domainType);
4141

4242
<T> boolean existsById(Object id, Class<T> domainType);
43-
4443
}

src/main/java/org/springframework/data/jdbc/mapping/model/ConversionCustomizer.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,5 +23,7 @@
2323
*/
2424
public interface ConversionCustomizer {
2525

26+
public static ConversionCustomizer NONE = __ -> {};
27+
2628
void customize(GenericConversionService conversions);
2729
}

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

Lines changed: 23 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -37,14 +37,15 @@
3737
import org.springframework.data.mapping.model.Property;
3838
import org.springframework.data.mapping.model.SimpleTypeHolder;
3939
import org.springframework.data.util.TypeInformation;
40-
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
40+
import org.springframework.util.Assert;
4141

4242
/**
4343
* {@link MappingContext} implementation for JDBC.
4444
*
4545
* @author Jens Schauder
4646
* @author Greg Turnquist
4747
* @author Kazuki Shimizu
48+
* @author Oliver Gierke
4849
* @since 1.0
4950
*/
5051
public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEntity<?>, JdbcPersistentProperty> {
@@ -56,24 +57,37 @@ public class JdbcMappingContext extends AbstractMappingContext<JdbcPersistentEnt
5657
));
5758

5859
@Getter private final NamingStrategy namingStrategy;
59-
@Getter private final NamedParameterJdbcOperations template;
6060
@Getter private SimpleTypeHolder simpleTypeHolder;
6161
private GenericConversionService conversions = getDefaultConversionService();
6262

63-
public JdbcMappingContext(NamingStrategy namingStrategy, NamedParameterJdbcOperations template,
64-
ConversionCustomizer customizer) {
63+
/**
64+
* Creates a new {@link JdbcMappingContext}.
65+
*/
66+
public JdbcMappingContext() {
67+
this(NamingStrategy.INSTANCE, ConversionCustomizer.NONE);
68+
}
69+
70+
public JdbcMappingContext(NamingStrategy namingStrategy) {
71+
this(namingStrategy, ConversionCustomizer.NONE);
72+
}
73+
74+
/**
75+
* Creates a new {@link JdbcMappingContext} using the given {@link NamingStrategy} and {@link ConversionCustomizer}.
76+
*
77+
* @param namingStrategy must not be {@literal null}.
78+
* @param customizer must not be {@literal null}.
79+
*/
80+
public JdbcMappingContext(NamingStrategy namingStrategy, ConversionCustomizer customizer) {
81+
82+
Assert.notNull(namingStrategy, "NamingStrategy must not be null!");
83+
Assert.notNull(customizer, "ConversionCustomizer must not be null!");
6584

6685
this.namingStrategy = namingStrategy;
67-
this.template = template;
6886

6987
customizer.customize(conversions);
7088
setSimpleTypeHolder(new SimpleTypeHolder(CUSTOM_SIMPLE_TYPES, true));
7189
}
7290

73-
public JdbcMappingContext(NamedParameterJdbcOperations template) {
74-
this(NamingStrategy.INSTANCE, template, __ -> {});
75-
}
76-
7791
@Override
7892
public void setSimpleTypeHolder(SimpleTypeHolder simpleTypes) {
7993
super.setSimpleTypeHolder(simpleTypes);

0 commit comments

Comments
 (0)