Skip to content

Commit 1764457

Browse files
committed
DATAJDBC-326 - Polishing.
Add Javadoc. Tweak naming and factory methods. Add equals/hashcode to Identifier. Extend tests. Original pull request: #118.
1 parent ade3324 commit 1764457

File tree

9 files changed

+268
-126
lines changed

9 files changed

+268
-126
lines changed

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

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

1818
import java.util.Map;
1919

20-
import org.springframework.data.relational.domain.Identifier;
2120
import org.springframework.data.mapping.PersistentPropertyPath;
2221
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
22+
import org.springframework.data.relational.domain.Identifier;
2323
import org.springframework.lang.Nullable;
2424

2525
/**
@@ -40,25 +40,25 @@ public interface DataAccessStrategy {
4040
* to get referenced are contained in this map. Must not be {@code null}.
4141
* @param <T> the type of the instance.
4242
* @return the id generated by the database if any.
43-
*
44-
* @deprecated use {@link #insert(Object, Class, Identifier)} instead.
43+
* @deprecated since 1.1, use {@link #insert(Object, Class, Identifier)} instead.
4544
*/
4645
@Deprecated
4746
<T> Object insert(T instance, Class<T> domainType, Map<String, Object> additionalParameters);
4847

49-
5048
/**
5149
* Inserts a the data of a single entity. Referenced entities don't get handled.
5250
*
5351
* @param instance the instance to be stored. Must not be {@code null}.
5452
* @param domainType the type of the instance. Must not be {@code null}.
55-
* @param identifier information about data that needs to be considered for the insert but which is not part of the entity.
56-
* Namely references back to a parent entity and key/index columns for entities that are stored in a {@link Map} or {@link java.util.List}.
53+
* @param identifier information about data that needs to be considered for the insert but which is not part of the
54+
* entity. Namely references back to a parent entity and key/index columns for entities that are stored in a
55+
* {@link Map} or {@link java.util.List}.
5756
* @param <T> the type of the instance.
5857
* @return the id generated by the database if any.
58+
* @since 1.1
5959
*/
6060
default <T> Object insert(T instance, Class<T> domainType, Identifier identifier){
61-
return insert(instance, domainType, identifier.getParametersByName());
61+
return insert(instance, domainType, identifier.toMap());
6262
}
6363

6464
/**

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

Lines changed: 7 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,6 @@
2929
import org.springframework.dao.DataRetrievalFailureException;
3030
import org.springframework.dao.EmptyResultDataAccessException;
3131
import org.springframework.dao.InvalidDataAccessApiUsageException;
32-
import org.springframework.data.jdbc.core.convert.JdbcIdentifierBuilder;
3332
import org.springframework.data.jdbc.support.JdbcUtil;
3433
import org.springframework.data.mapping.PersistentPropertyAccessor;
3534
import org.springframework.data.mapping.PersistentPropertyPath;
@@ -59,10 +58,6 @@
5958
@RequiredArgsConstructor
6059
public class DefaultDataAccessStrategy implements DataAccessStrategy {
6160

62-
private static final String ENTITY_NEW_AFTER_INSERT = "Entity [%s] still 'new' after insert. Please set either"
63-
+ " the id property in a BeforeInsert event handler, or ensure the database creates a value and your "
64-
+ "JDBC driver returns it.";
65-
6661
private final @NonNull SqlGeneratorSource sqlGeneratorSource;
6762
private final @NonNull RelationalMappingContext context;
6863
private final @NonNull RelationalConverter converter;
@@ -89,7 +84,7 @@ public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, Relation
8984
*/
9085
@Override
9186
public <T> Object insert(T instance, Class<T> domainType, Map<String, Object> additionalParameters) {
92-
return insert(instance, domainType, JdbcIdentifierBuilder.from(additionalParameters).build());
87+
return insert(instance, domainType, Identifier.from(additionalParameters));
9388
}
9489

9590
/*
@@ -102,10 +97,9 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier)
10297
KeyHolder holder = new GeneratedKeyHolder();
10398
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(domainType);
10499

105-
Map<String, Object> parameters = new LinkedHashMap<>();
106-
identifier.forEach(identifierValue -> {
107-
parameters.put(identifierValue.getName(),
108-
converter.writeValue(identifierValue.getValue(), ClassTypeInformation.from(identifierValue.getTargetType())));
100+
Map<String, Object> parameters = new LinkedHashMap<>(identifier.size());
101+
identifier.forEach((name, value, type) -> {
102+
parameters.put(name, converter.writeValue(value, ClassTypeInformation.from(type)));
109103
});
110104

111105
MapSqlParameterSource parameterSource = getPropertyMap(instance, persistentEntity, "");
@@ -298,7 +292,7 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
298292
return result;
299293
}
300294

301-
private <S, T> MapSqlParameterSource getPropertyMap(final S instance, RelationalPersistentEntity<S> persistentEntity,
295+
private <S, T> MapSqlParameterSource getPropertyMap(S instance, RelationalPersistentEntity<S> persistentEntity,
302296
String prefix) {
303297

304298
MapSqlParameterSource parameters = new MapSqlParameterSource();
@@ -314,8 +308,8 @@ private <S, T> MapSqlParameterSource getPropertyMap(final S instance, Relational
314308
if (property.isEmbedded()) {
315309

316310
Object value = propertyAccessor.getProperty(property);
317-
final RelationalPersistentEntity<?> embeddedEntity = context.getPersistentEntity(property.getType());
318-
final MapSqlParameterSource additionalParameters = getPropertyMap((T) value,
311+
RelationalPersistentEntity<?> embeddedEntity = context.getPersistentEntity(property.getType());
312+
MapSqlParameterSource additionalParameters = getPropertyMap((T) value,
319313
(RelationalPersistentEntity<T>) embeddedEntity, prefix + property.getEmbeddedPrefix());
320314
parameters.addValues(additionalParameters.getValues());
321315
} else {

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreter.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.util.Map;
2222

2323
import org.springframework.data.jdbc.core.convert.JdbcIdentifierBuilder;
24-
import org.springframework.data.relational.domain.Identifier;
2524
import org.springframework.data.mapping.PersistentPropertyPath;
2625
import org.springframework.data.relational.core.conversion.DbAction;
2726
import org.springframework.data.relational.core.conversion.DbAction.Delete;
@@ -37,6 +36,7 @@
3736
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3837
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
3938
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
39+
import org.springframework.data.relational.domain.Identifier;
4040
import org.springframework.lang.Nullable;
4141

4242
/**
@@ -142,7 +142,7 @@ public <T> void interpret(DeleteAllRoot<T> deleteAllRoot) {
142142
accessStrategy.deleteAll(deleteAllRoot.getEntityType());
143143
}
144144

145-
private <T> Identifier getParentKeys(DbAction.WithDependingOn<?> action) {
145+
private Identifier getParentKeys(DbAction.WithDependingOn<?> action) {
146146

147147
DbAction.WithEntity<?> dependingOn = action.getDependingOn();
148148

@@ -152,7 +152,8 @@ private <T> Identifier getParentKeys(DbAction.WithDependingOn<?> action) {
152152
JdbcIdentifierBuilder identifier = JdbcIdentifierBuilder //
153153
.forBackReferences(action.getPropertyPath(), id);
154154

155-
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers().entrySet()) {
155+
for (Map.Entry<PersistentPropertyPath<RelationalPersistentProperty>, Object> qualifier : action.getQualifiers()
156+
.entrySet()) {
156157
identifier = identifier.withQualifier(qualifier.getKey(), qualifier.getValue());
157158
}
158159

spring-data-jdbc/src/main/java/org/springframework/data/jdbc/core/convert/JdbcIdentifierBuilder.java

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

18-
import java.util.Map;
19-
2018
import org.springframework.data.mapping.PersistentPropertyPath;
2119
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2220
import org.springframework.data.relational.domain.Identifier;
2321
import org.springframework.lang.Nullable;
2422

2523
/**
24+
* Builder for {@link Identifier}. Mainly for internal use within the framework
25+
*
2626
* @author Jens Schauder
2727
* @since 1.1
2828
*/
@@ -38,23 +38,13 @@ public static JdbcIdentifierBuilder empty() {
3838
return new JdbcIdentifierBuilder(Identifier.empty());
3939
}
4040

41-
public static JdbcIdentifierBuilder from(Map<String, Object> additionalParameters) {
42-
43-
Identifier[] identifier = new Identifier[] { Identifier.empty() };
44-
45-
additionalParameters
46-
.forEach((k, v) -> identifier[0] = identifier[0].add(k, v, v == null ? Object.class : v.getClass()));
47-
48-
return new JdbcIdentifierBuilder(identifier[0]);
49-
}
50-
5141
/**
5242
* Creates ParentKeys with backreference for the given path and value of the parents id.
5343
*/
5444
public static JdbcIdentifierBuilder forBackReferences(PersistentPropertyPath<RelationalPersistentProperty> path,
5545
@Nullable Object value) {
5646

57-
Identifier identifier = Identifier.simple( //
47+
Identifier identifier = Identifier.of( //
5848
path.getRequiredLeafProperty().getReverseColumnName(), //
5949
value, //
6050
getLastIdProperty(path).getColumnType() //
@@ -66,7 +56,7 @@ public static JdbcIdentifierBuilder forBackReferences(PersistentPropertyPath<Rel
6656
public JdbcIdentifierBuilder withQualifier(PersistentPropertyPath<RelationalPersistentProperty> path, Object value) {
6757

6858
RelationalPersistentProperty leafProperty = path.getRequiredLeafProperty();
69-
identifier = identifier.add(leafProperty.getKeyColumn(), value, leafProperty.getQualifierColumnType());
59+
identifier = identifier.withPart(leafProperty.getKeyColumn(), value, leafProperty.getQualifierColumnType());
7060

7161
return this;
7262
}

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

Lines changed: 15 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,17 +22,18 @@
2222

2323
import org.apache.ibatis.session.SqlSession;
2424
import org.mybatis.spring.SqlSessionTemplate;
25+
2526
import org.springframework.data.jdbc.core.CascadingDataAccessStrategy;
2627
import org.springframework.data.jdbc.core.DataAccessStrategy;
2728
import org.springframework.data.jdbc.core.DefaultDataAccessStrategy;
2829
import org.springframework.data.jdbc.core.DelegatingDataAccessStrategy;
29-
import org.springframework.data.relational.domain.Identifier;
3030
import org.springframework.data.jdbc.core.SqlGeneratorSource;
3131
import org.springframework.data.mapping.PersistentPropertyPath;
3232
import org.springframework.data.mapping.PropertyPath;
3333
import org.springframework.data.relational.core.conversion.RelationalConverter;
3434
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3535
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
36+
import org.springframework.data.relational.domain.Identifier;
3637
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
3738
import org.springframework.util.Assert;
3839

@@ -124,7 +125,7 @@ public void setNamespaceStrategy(NamespaceStrategy namespaceStrategy) {
124125
this.namespaceStrategy = namespaceStrategy;
125126
}
126127

127-
/*
128+
/*
128129
* (non-Javadoc)
129130
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map)
130131
*/
@@ -144,13 +145,13 @@ public <T> Object insert(T instance, Class<T> domainType, Map<String, Object> ad
144145
@Override
145146
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier) {
146147

147-
MyBatisContext myBatisContext = new MyBatisContext(null, instance, domainType, identifier.getParametersByName());
148+
MyBatisContext myBatisContext = new MyBatisContext(null, instance, domainType, identifier.toMap());
148149
sqlSession().insert(namespace(domainType) + ".insert", myBatisContext);
149150

150151
return myBatisContext.getId();
151152
}
152153

153-
/*
154+
/*
154155
* (non-Javadoc)
155156
* @see org.springframework.data.jdbc.core.DataAccessStrategy#update(java.lang.Object, java.lang.Class)
156157
*/
@@ -161,7 +162,7 @@ public <S> boolean update(S instance, Class<S> domainType) {
161162
new MyBatisContext(null, instance, domainType, Collections.emptyMap())) != 0;
162163
}
163164

164-
/*
165+
/*
165166
* (non-Javadoc)
166167
* @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, java.lang.Class)
167168
*/
@@ -172,7 +173,7 @@ public void delete(Object id, Class<?> domainType) {
172173
new MyBatisContext(id, null, domainType, Collections.emptyMap()));
173174
}
174175

175-
/*
176+
/*
176177
* (non-Javadoc)
177178
* @see org.springframework.data.jdbc.core.DataAccessStrategy#delete(java.lang.Object, org.springframework.data.mapping.PersistentPropertyPath)
178179
*/
@@ -185,7 +186,7 @@ public void delete(Object rootId, PersistentPropertyPath<RelationalPersistentPro
185186
Collections.emptyMap()));
186187
}
187188

188-
/*
189+
/*
189190
* (non-Javadoc)
190191
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(java.lang.Class)
191192
*/
@@ -198,7 +199,7 @@ public <T> void deleteAll(Class<T> domainType) {
198199
);
199200
}
200201

201-
/*
202+
/*
202203
* (non-Javadoc)
203204
* @see org.springframework.data.jdbc.core.DataAccessStrategy#deleteAll(org.springframework.data.mapping.PersistentPropertyPath)
204205
*/
@@ -214,7 +215,7 @@ public void deleteAll(PersistentPropertyPath<RelationalPersistentProperty> prope
214215
);
215216
}
216217

217-
/*
218+
/*
218219
* (non-Javadoc)
219220
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findById(java.lang.Object, java.lang.Class)
220221
*/
@@ -224,7 +225,7 @@ public <T> T findById(Object id, Class<T> domainType) {
224225
new MyBatisContext(id, null, domainType, Collections.emptyMap()));
225226
}
226227

227-
/*
228+
/*
228229
* (non-Javadoc)
229230
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAll(java.lang.Class)
230231
*/
@@ -234,7 +235,7 @@ public <T> Iterable<T> findAll(Class<T> domainType) {
234235
new MyBatisContext(null, null, domainType, Collections.emptyMap()));
235236
}
236237

237-
/*
238+
/*
238239
* (non-Javadoc)
239240
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllById(java.lang.Iterable, java.lang.Class)
240241
*/
@@ -244,7 +245,7 @@ public <T> Iterable<T> findAllById(Iterable<?> ids, Class<T> domainType) {
244245
new MyBatisContext(ids, null, domainType, Collections.emptyMap()));
245246
}
246247

247-
/*
248+
/*
248249
* (non-Javadoc)
249250
* @see org.springframework.data.jdbc.core.DataAccessStrategy#findAllByProperty(java.lang.Object, org.springframework.data.relational.core.mapping.RelationalPersistentProperty)
250251
*/
@@ -255,7 +256,7 @@ public <T> Iterable<T> findAllByProperty(Object rootId, RelationalPersistentProp
255256
new MyBatisContext(rootId, null, property.getType(), Collections.emptyMap()));
256257
}
257258

258-
/*
259+
/*
259260
* (non-Javadoc)
260261
* @see org.springframework.data.jdbc.core.DataAccessStrategy#existsById(java.lang.Object, java.lang.Class)
261262
*/
@@ -265,7 +266,7 @@ public <T> boolean existsById(Object id, Class<T> domainType) {
265266
new MyBatisContext(id, null, domainType, Collections.emptyMap()));
266267
}
267268

268-
/*
269+
/*
269270
* (non-Javadoc)
270271
* @see org.springframework.data.jdbc.core.DataAccessStrategy#count(java.lang.Class)
271272
*/

spring-data-jdbc/src/test/java/org/springframework/data/jdbc/core/DefaultJdbcInterpreterUnitTests.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121

2222
import org.junit.Test;
2323
import org.mockito.ArgumentCaptor;
24+
2425
import org.springframework.data.annotation.Id;
2526
import org.springframework.data.jdbc.core.mapping.JdbcMappingContext;
2627
import org.springframework.data.relational.core.conversion.DbAction.Insert;
@@ -68,7 +69,7 @@ public void insertDoesHonourNamingStrategyForBackReference() {
6869
ArgumentCaptor<Identifier> argumentCaptor = ArgumentCaptor.forClass(Identifier.class);
6970
verify(dataAccessStrategy).insert(eq(element), eq(Element.class), argumentCaptor.capture());
7071

71-
assertThat(argumentCaptor.getValue().getParameters()) //
72+
assertThat(argumentCaptor.getValue().getParts()) //
7273
.extracting("name", "value", "targetType") //
7374
.containsExactly(tuple(BACK_REFERENCE, CONTAINER_ID, Long.class));
7475
}
@@ -83,7 +84,7 @@ public void idOfParentGetsPassedOnAsAdditionalParameterIfNoIdGotGenerated() {
8384
ArgumentCaptor<Identifier> argumentCaptor = ArgumentCaptor.forClass(Identifier.class);
8485
verify(dataAccessStrategy).insert(eq(element), eq(Element.class), argumentCaptor.capture());
8586

86-
assertThat(argumentCaptor.getValue().getParameters()) //
87+
assertThat(argumentCaptor.getValue().getParts()) //
8788
.extracting("name", "value", "targetType") //
8889
.containsExactly(tuple(BACK_REFERENCE, CONTAINER_ID, Long.class));
8990
}
@@ -98,7 +99,7 @@ public void generatedIdOfParentGetsPassedOnAsAdditionalParameter() {
9899
ArgumentCaptor<Identifier> argumentCaptor = ArgumentCaptor.forClass(Identifier.class);
99100
verify(dataAccessStrategy).insert(eq(element), eq(Element.class), argumentCaptor.capture());
100101

101-
assertThat(argumentCaptor.getValue().getParameters()) //
102+
assertThat(argumentCaptor.getValue().getParts()) //
102103
.extracting("name", "value", "targetType") //
103104
.containsExactly(tuple(BACK_REFERENCE, CONTAINER_ID, Long.class));
104105
}

0 commit comments

Comments
 (0)