Skip to content

Commit 0214105

Browse files
committed
Use new enum IdValueSource instead of a boolean to indicate the source of an id value for inserts.
+ This introduces a new state for this indicator - IdValueSource.NONE. Inserts with this indicator value are now batched separately and no longer use the id generating insert strategies.
1 parent a2216e0 commit 0214105

21 files changed

+313
-260
lines changed

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@ <T> void executeInsertRoot(DbAction.InsertRoot<T> insert) {
9090
T rootEntity = RelationalEntityVersionUtils.setVersionNumberOnEntity( //
9191
insert.getEntity(), initialVersion, persistentEntity, converter);
9292

93-
id = accessStrategy.insert(rootEntity, insert.getEntityType(), Identifier.empty(), insert.isIncludeId());
93+
id = accessStrategy.insert(rootEntity, insert.getEntityType(), Identifier.empty(), insert.getIdValueSource());
9494

9595
setNewVersion(initialVersion);
9696
} else {
97-
id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty(), insert.isIncludeId());
97+
id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), Identifier.empty(), insert.getIdValueSource());
9898
}
9999

100100
add(new DbActionExecutionResult(insert, id));
@@ -103,7 +103,7 @@ <T> void executeInsertRoot(DbAction.InsertRoot<T> insert) {
103103
<T> void executeInsert(DbAction.Insert<T> insert) {
104104

105105
Identifier parentKeys = getParentKeys(insert, converter);
106-
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), parentKeys, insert.isIncludeId());
106+
Object id = accessStrategy.insert(insert.getEntity(), insert.getEntityType(), parentKeys, insert.getIdValueSource());
107107
add(new DbActionExecutionResult(insert, id));
108108
}
109109

@@ -114,7 +114,7 @@ <T> void executeInsertBatch(DbAction.InsertBatch<T> insertBatch) {
114114
.map(insert -> InsertSubject.describedBy(insert.getEntity(), getParentKeys(insert, converter)))
115115
.collect(Collectors.toList());
116116

117-
Object[] ids = accessStrategy.insert(insertSubjects, insertBatch.getEntityType(), insertBatch.isIncludeId());
117+
Object[] ids = accessStrategy.insert(insertSubjects, insertBatch.getEntityType(), insertBatch.getIdValueSource());
118118

119119
for (int i = 0; i < inserts.size(); i++) {
120120
add(new DbActionExecutionResult(inserts.get(i), ids.length > 0 ? ids[i] : null));

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.data.domain.Pageable;
2424
import org.springframework.data.domain.Sort;
2525
import org.springframework.data.mapping.PersistentPropertyPath;
26+
import org.springframework.data.relational.core.conversion.IdValueSource;
2627
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2728
import org.springframework.data.relational.core.sql.LockMode;
2829

@@ -51,13 +52,13 @@ public CascadingDataAccessStrategy(List<DataAccessStrategy> strategies) {
5152
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys)
5253
*/
5354
@Override
54-
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, boolean includeId) {
55-
return collect(das -> das.insert(instance, domainType, identifier, false));
55+
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource) {
56+
return collect(das -> das.insert(instance, domainType, identifier, idValueSource));
5657
}
5758

5859
@Override
59-
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, boolean includeId) {
60-
return collect(das -> das.insert(insertSubjects, domainType, includeId));
60+
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, IdValueSource idValueSource) {
61+
return collect(das -> das.insert(insertSubjects, domainType, idValueSource));
6162
}
6263

6364
/*

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import org.springframework.data.domain.Sort;
2424
import org.springframework.data.jdbc.core.JdbcAggregateOperations;
2525
import org.springframework.data.mapping.PersistentPropertyPath;
26+
import org.springframework.data.relational.core.conversion.IdValueSource;
2627
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2728
import org.springframework.data.relational.core.sql.LockMode;
2829
import org.springframework.lang.Nullable;
@@ -51,13 +52,13 @@ public interface DataAccessStrategy extends RelationResolver {
5152
* {@link Map} or {@link List}.
5253
* @return the id generated by the database if any.
5354
* @since 1.1
54-
* @deprecated since 2.4, use {@link #insert(T, Class, Identifier, boolean)}. This will no longer insert as expected
55-
* when the id property of the instance is pre-populated.
55+
* @deprecated since 2.4, use {@link #insert(Object, Class, Identifier, IdValueSource)}. This will no longer insert as
56+
* expected when the id property of the instance is pre-populated.
5657
*/
5758
@Nullable
5859
@Deprecated
5960
default <T> Object insert(T instance, Class<T> domainType, Identifier identifier) {
60-
return insert(instance, domainType, identifier, false);
61+
return insert(instance, domainType, identifier, IdValueSource.GENERATED);
6162
}
6263

6364
/**
@@ -69,12 +70,12 @@ default <T> Object insert(T instance, Class<T> domainType, Identifier identifier
6970
* @param identifier information about data that needs to be considered for the insert but which is not part of the
7071
* entity. Namely references back to a parent entity and key/index columns for entities that are stored in a
7172
* {@link Map} or {@link List}.
72-
* @param includeId an indicator of whether the insert includes the id.
73+
* @param idValueSource the {@link IdValueSource} for the insert.
7374
* @return the id generated by the database if any.
7475
* @since 2.4
7576
*/
7677
@Nullable
77-
<T> Object insert(T instance, Class<T> domainType, Identifier identifier, boolean includeId);
78+
<T> Object insert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource);
7879

7980
/**
8081
* Inserts the data of a multiple entities.
@@ -83,12 +84,12 @@ default <T> Object insert(T instance, Class<T> domainType, Identifier identifier
8384
* @param insertSubjects the subjects to be inserted, where each subject contains the instance and its identifier.
8485
* Must not be {@code null}.
8586
* @param domainType the type of the instance. Must not be {@code null}.
86-
* @param includeId an indicator of whether the insert includes the id.
87+
* @param idValueSource the {@link IdValueSource} for the insert.
8788
* @return the ids corresponding to each record that was inserted, if ids were generated. If ids were not generated,
8889
* elements will be {@code null}.
8990
* @since 2.4
9091
*/
91-
<T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, boolean includeId);
92+
<T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, IdValueSource idValueSource);
9293

9394
/**
9495
* Updates the data of a single entity in the database. Referenced entities don't get handled.

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

Lines changed: 7 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.domain.Pageable;
2828
import org.springframework.data.domain.Sort;
2929
import org.springframework.data.mapping.PersistentPropertyPath;
30+
import org.springframework.data.relational.core.conversion.IdValueSource;
3031
import org.springframework.data.relational.core.mapping.PersistentPropertyPathExtension;
3132
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3233
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
@@ -98,26 +99,26 @@ public DefaultDataAccessStrategy(SqlGeneratorSource sqlGeneratorSource, Relation
9899
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, java.util.Map)
99100
*/
100101
@Override
101-
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, boolean includeId) {
102+
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource) {
102103

103-
SqlIdentifierParameterSource parameterSource = sqlParametersFactory.forInsert(instance, domainType, identifier, includeId);
104+
SqlIdentifierParameterSource parameterSource = sqlParametersFactory.forInsert(instance, domainType, identifier, idValueSource);
104105

105106
String insertSql = sql(domainType).getInsert(parameterSource.getIdentifiers());
106107

107-
return insertStrategyFactory.insertStrategy(!includeId, getIdColumn(domainType)).execute(insertSql, parameterSource);
108+
return insertStrategyFactory.insertStrategy(idValueSource, getIdColumn(domainType)).execute(insertSql, parameterSource);
108109
}
109110

110111
@Override
111-
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, boolean includeId) {
112+
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, IdValueSource idValueSource) {
112113

113114
Assert.notEmpty(insertSubjects, "Batch insert must contain at least one InsertSubject");
114115
SqlIdentifierParameterSource[] sqlParameterSources = insertSubjects.stream()
115-
.map(insertSubject -> sqlParametersFactory.forInsert(insertSubject.getInstance(), domainType, insertSubject.getIdentifier(), includeId))
116+
.map(insertSubject -> sqlParametersFactory.forInsert(insertSubject.getInstance(), domainType, insertSubject.getIdentifier(), idValueSource))
116117
.toArray(SqlIdentifierParameterSource[]::new);
117118

118119
String insertSql = sql(domainType).getInsert(sqlParameterSources[0].getIdentifiers());
119120

120-
return insertStrategyFactory.batchInsertStrategy(!includeId, getIdColumn(domainType)).execute(insertSql, sqlParameterSources);
121+
return insertStrategyFactory.batchInsertStrategy(idValueSource, getIdColumn(domainType)).execute(insertSql, sqlParameterSources);
121122
}
122123

123124
/*

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

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
import org.springframework.data.domain.Pageable;
1919
import org.springframework.data.domain.Sort;
2020
import org.springframework.data.mapping.PersistentPropertyPath;
21+
import org.springframework.data.relational.core.conversion.IdValueSource;
2122
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
2223
import org.springframework.data.relational.core.sql.LockMode;
2324
import org.springframework.util.Assert;
@@ -44,13 +45,13 @@ public class DelegatingDataAccessStrategy implements DataAccessStrategy {
4445
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, org.springframework.data.jdbc.core.ParentKeys)
4546
*/
4647
@Override
47-
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, boolean includeId) {
48-
return delegate.insert(instance, domainType, identifier, includeId);
48+
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource) {
49+
return delegate.insert(instance, domainType, identifier, idValueSource);
4950
}
5051

5152
@Override
52-
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, boolean includeId) {
53-
return delegate.insert(insertSubjects, domainType, includeId);
53+
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, IdValueSource idValueSource) {
54+
return delegate.insert(insertSubjects, domainType, idValueSource);
5455
}
5556

5657
/*

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

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

18+
import org.springframework.data.relational.core.conversion.IdValueSource;
1819
import org.springframework.data.relational.core.dialect.Dialect;
1920
import org.springframework.data.relational.core.sql.SqlIdentifier;
2021
import org.springframework.jdbc.core.namedparam.NamedParameterJdbcOperations;
@@ -41,35 +42,33 @@ public InsertStrategyFactory(NamedParameterJdbcOperations namedParameterJdbcOper
4142
}
4243

4344
/**
44-
* @param generateIds whether the insert is expected to generate ids.
45+
* @param idValueSource the {@link IdValueSource} for the insert.
4546
* @param idColumn the identifier for the id, if an id is expected to be generated. May be {@code null}.
4647
* @return the {@link InsertStrategy} to be used for the insert.
4748
* @since 2.4
4849
*/
49-
InsertStrategy insertStrategy(boolean generateIds, @Nullable SqlIdentifier idColumn) {
50+
InsertStrategy insertStrategy(IdValueSource idValueSource, @Nullable SqlIdentifier idColumn) {
5051

51-
if (generateIds) {
52+
if (IdValueSource.GENERATED.equals(idValueSource)) {
5253
return new IdGeneratingInsertStrategy(dialect, namedParameterJdbcOperations, idColumn);
53-
} else {
54-
return new DefaultInsertStrategy(namedParameterJdbcOperations);
5554
}
55+
return new DefaultInsertStrategy(namedParameterJdbcOperations);
5656
}
5757

5858
/**
59-
* @param generateIds whether the batch insert is expected to generate ids.
59+
* @param idValueSource the {@link IdValueSource} for the insert.
6060
* @param idColumn the identifier for the id, if an ids are expected to be generated. May be {@code null}.
6161
* @return the {@link BatchInsertStrategy} to be used for the batch insert.
6262
* @since 2.4
6363
*/
64-
BatchInsertStrategy batchInsertStrategy(boolean generateIds, @Nullable SqlIdentifier idColumn) {
64+
BatchInsertStrategy batchInsertStrategy(IdValueSource idValueSource, @Nullable SqlIdentifier idColumn) {
6565

66-
if (generateIds) {
66+
if (IdValueSource.GENERATED.equals(idValueSource)) {
6767
return new IdGeneratingBatchInsertStrategy(
6868
new IdGeneratingInsertStrategy(dialect, namedParameterJdbcOperations, idColumn),
6969
dialect, batchJdbcOperations, idColumn);
70-
} else {
71-
return new DefaultBatchInsertStrategy(namedParameterJdbcOperations);
7270
}
71+
return new DefaultBatchInsertStrategy(namedParameterJdbcOperations);
7372
}
7473

7574
private static class DefaultInsertStrategy implements InsertStrategy {

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
import org.springframework.data.jdbc.support.JdbcUtil;
2828
import org.springframework.data.mapping.PersistentProperty;
2929
import org.springframework.data.mapping.PersistentPropertyAccessor;
30+
import org.springframework.data.relational.core.conversion.IdValueSource;
3031
import org.springframework.data.relational.core.dialect.Dialect;
3132
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3233
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;
@@ -64,19 +65,19 @@ public SqlParametersFactory(RelationalMappingContext context, JdbcConverter conv
6465
* @param identifier information about data that needs to be considered for the insert but which is not part of the
6566
* entity. Namely references back to a parent entity and key/index columns for entities that are stored in a
6667
* {@link Map} or {@link List}.
67-
* @param includeId an indicator of whether the insert includes the id.
68+
* @param idValueSource the {@link IdValueSource} for the insert.
6869
* @return the {@link SqlIdentifierParameterSource} for the insert. Guaranteed to not be {@code null}.
6970
* @since 2.4
7071
*/
71-
<T> SqlIdentifierParameterSource forInsert(T instance, Class<T> domainType, Identifier identifier, boolean includeId) {
72+
<T> SqlIdentifierParameterSource forInsert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource) {
7273

7374
RelationalPersistentEntity<T> persistentEntity = getRequiredPersistentEntity(domainType);
7475
SqlIdentifierParameterSource parameterSource = getParameterSource(instance, persistentEntity, "",
7576
PersistentProperty::isIdProperty, dialect.getIdentifierProcessing());
7677

7778
identifier.forEach((name, value, type) -> addConvertedPropertyValue(parameterSource, name, value, type));
7879

79-
if (includeId) {
80+
if (IdValueSource.PROVIDED.equals(idValueSource)) {
8081

8182
RelationalPersistentProperty idProperty = persistentEntity.getRequiredIdProperty();
8283
Object idValue = persistentEntity.getIdentifierAccessor(instance).getRequiredIdentifier();

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.springframework.data.jdbc.core.convert.*;
3434
import org.springframework.data.mapping.PersistentPropertyPath;
3535
import org.springframework.data.mapping.PropertyPath;
36+
import org.springframework.data.relational.core.conversion.IdValueSource;
3637
import org.springframework.data.relational.core.dialect.Dialect;
3738
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
3839
import org.springframework.data.relational.core.mapping.RelationalPersistentProperty;
@@ -151,7 +152,7 @@ public void setNamespaceStrategy(NamespaceStrategy namespaceStrategy) {
151152
* @see org.springframework.data.jdbc.core.DataAccessStrategy#insert(java.lang.Object, java.lang.Class, Identifier, boolean)
152153
*/
153154
@Override
154-
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, boolean includeId) {
155+
public <T> Object insert(T instance, Class<T> domainType, Identifier identifier, IdValueSource idValueSource) {
155156

156157
MyBatisContext myBatisContext = new MyBatisContext(identifier, instance, domainType);
157158
sqlSession().insert(namespace(domainType) + ".insert", myBatisContext);
@@ -160,10 +161,10 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier,
160161
}
161162

162163
@Override
163-
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, boolean includeId) {
164+
public <T> Object[] insert(List<InsertSubject<T>> insertSubjects, Class<T> domainType, IdValueSource idValueSource) {
164165

165166
return insertSubjects.stream()
166-
.map(insertSubject -> insert(insertSubject.getInstance(), domainType, insertSubject.getIdentifier(), includeId))
167+
.map(insertSubject -> insert(insertSubject.getInstance(), domainType, insertSubject.getIdentifier(), idValueSource))
167168
.toArray();
168169
}
169170

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@
4040
import org.springframework.data.mapping.PersistentPropertyPath;
4141
import org.springframework.data.mapping.PersistentPropertyPaths;
4242
import org.springframework.data.relational.core.conversion.DbAction;
43+
import org.springframework.data.relational.core.conversion.IdValueSource;
4344
import org.springframework.data.relational.core.conversion.MutableAggregateChange;
4445
import org.springframework.data.relational.core.mapping.Column;
4546
import org.springframework.data.relational.core.mapping.Embedded;
@@ -69,7 +70,7 @@ public class AggregateChangeIdGenerationImmutableUnitTests {
6970

7071
RelationalMappingContext context = new RelationalMappingContext();
7172
JdbcConverter converter = mock(JdbcConverter.class);
72-
DbAction.WithEntity<?> rootInsert = new DbAction.InsertRoot<>(entity, false);
73+
DbAction.WithEntity<?> rootInsert = new DbAction.InsertRoot<>(entity, IdValueSource.GENERATED);
7374

7475
private DataAccessStrategy accessStrategy = mock(DataAccessStrategy.class);
7576

@@ -394,7 +395,7 @@ DbAction.Insert<?> createInsert(String propertyName, Object value, @Nullable Obj
394395

395396
DbAction.Insert<Object> insert = new DbAction.Insert<>(value,
396397
context.getPersistentPropertyPath(propertyName, DummyEntity.class), rootInsert,
397-
singletonMap(toPath(propertyName), key), false);
398+
singletonMap(toPath(propertyName), key), IdValueSource.GENERATED);
398399

399400
return insert;
400401
}
@@ -405,7 +406,7 @@ DbAction.Insert<?> createDeepInsert(String propertyName, Object value, Object ke
405406
PersistentPropertyPath<RelationalPersistentProperty> propertyPath = toPath(
406407
parentInsert.getPropertyPath().toDotPath() + "." + propertyName);
407408
DbAction.Insert<Object> insert = new DbAction.Insert<>(value, propertyPath, parentInsert,
408-
singletonMap(propertyPath, key), false);
409+
singletonMap(propertyPath, key), IdValueSource.GENERATED);
409410

410411
return insert;
411412
}

0 commit comments

Comments
 (0)