Skip to content

Commit 304345c

Browse files
rtlustyschauder
authored andcommitted
Don't retrieve generated keys on INSERT if id is set.
Closes #933 Original pull request #939
1 parent 0e8e8a4 commit 304345c

File tree

2 files changed

+58
-16
lines changed

2 files changed

+58
-16
lines changed

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

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,7 @@
6666
* @author Milan Milanov
6767
* @author Myeonghyeon Lee
6868
* @author Yunyoung LEE
69+
* @author Radim Tlusty
6970
* @since 1.1
7071
*/
7172
public class DefaultDataAccessStrategy implements DataAccessStrategy {
@@ -120,24 +121,33 @@ public <T> Object insert(T instance, Class<T> domainType, Identifier identifier)
120121
addConvertedPropertyValue(parameterSource, idProperty, idValue, idProperty.getColumnName());
121122
}
122123

123-
KeyHolder holder = new GeneratedKeyHolder();
124-
125-
IdGeneration idGeneration = sqlGeneratorSource.getDialect().getIdGeneration();
126124
String insertSql = sqlGenerator.getInsert(new HashSet<>(parameterSource.getIdentifiers()));
127125

128-
if (idGeneration.driverRequiresKeyColumnNames()) {
126+
if (idValue == null) {
129127

130-
String[] keyColumnNames = getKeyColumnNames(domainType);
131-
if (keyColumnNames.length == 0) {
132-
operations.update(insertSql, parameterSource, holder);
128+
KeyHolder holder = new GeneratedKeyHolder();
129+
130+
IdGeneration idGeneration = sqlGeneratorSource.getDialect().getIdGeneration();
131+
132+
if (idGeneration.driverRequiresKeyColumnNames()) {
133+
134+
String[] keyColumnNames = getKeyColumnNames(domainType);
135+
if (keyColumnNames.length == 0) {
136+
operations.update(insertSql, parameterSource, holder);
137+
} else {
138+
operations.update(insertSql, parameterSource, holder, keyColumnNames);
139+
}
133140
} else {
134-
operations.update(insertSql, parameterSource, holder, keyColumnNames);
141+
operations.update(insertSql, parameterSource, holder);
135142
}
136-
} else {
137-
operations.update(insertSql, parameterSource, holder);
143+
144+
return getIdFromHolder(holder, persistentEntity);
138145
}
146+
else {
139147

140-
return getIdFromHolder(holder, persistentEntity);
148+
operations.update(insertSql, parameterSource);
149+
return null;
150+
}
141151
}
142152

143153
/*

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

Lines changed: 37 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -58,11 +58,13 @@
5858
* @author Mark Paluch
5959
* @author Myeonghyeon Lee
6060
* @author Myat Min
61+
* @author Radim Tlusty
6162
*/
6263
public class DefaultDataAccessStrategyUnitTests {
6364

6465
public static final long ID_FROM_ADDITIONAL_VALUES = 23L;
6566
public static final long ORIGINAL_ID = 4711L;
67+
public static final long GENERATED_ID = 17;
6668

6769
NamedParameterJdbcOperations namedJdbcOperations = mock(NamedParameterJdbcOperations.class);
6870
JdbcOperations jdbcOperations = mock(JdbcOperations.class);
@@ -99,7 +101,7 @@ public void additionalParameterForIdDoesNotLeadToDuplicateParameters() {
99101
accessStrategy.insert(new DummyEntity(ORIGINAL_ID), DummyEntity.class, Identifier.from(additionalParameters));
100102

101103
verify(namedJdbcOperations).update(eq("INSERT INTO \"DUMMY_ENTITY\" (\"ID\") VALUES (:ID)"),
102-
paramSourceCaptor.capture(), any(KeyHolder.class));
104+
paramSourceCaptor.capture());
103105
}
104106

105107
@Test // DATAJDBC-146
@@ -111,7 +113,7 @@ public void additionalParametersGetAddedToStatement() {
111113

112114
accessStrategy.insert(new DummyEntity(ORIGINAL_ID), DummyEntity.class, Identifier.from(additionalParameters));
113115

114-
verify(namedJdbcOperations).update(sqlCaptor.capture(), paramSourceCaptor.capture(), any(KeyHolder.class));
116+
verify(namedJdbcOperations).update(sqlCaptor.capture(), paramSourceCaptor.capture());
115117

116118
assertThat(sqlCaptor.getValue()) //
117119
.containsSubsequence("INSERT INTO \"DUMMY_ENTITY\" (", "\"ID\"", ") VALUES (", ":id", ")") //
@@ -131,7 +133,7 @@ public void considersConfiguredWriteConverter() {
131133

132134
accessStrategy.insert(entity, EntityWithBoolean.class, Identifier.empty());
133135

134-
verify(namedJdbcOperations).update(sqlCaptor.capture(), paramSourceCaptor.capture(), any(KeyHolder.class));
136+
verify(namedJdbcOperations).update(sqlCaptor.capture(), paramSourceCaptor.capture());
135137

136138
assertThat(paramSourceCaptor.getValue().getValue("id")).isEqualTo(ORIGINAL_ID);
137139
assertThat(paramSourceCaptor.getValue().getValue("flag")).isEqualTo("T");
@@ -150,7 +152,7 @@ public void considersConfiguredWriteConverterForIdValueObjects() {
150152

151153
accessStrategy.insert(entity, WithValueObjectId.class, Identifier.empty());
152154

153-
verify(namedJdbcOperations).update(anyString(), paramSourceCaptor.capture(), any(KeyHolder.class));
155+
verify(namedJdbcOperations).update(anyString(), paramSourceCaptor.capture());
154156

155157
assertThat(paramSourceCaptor.getValue().getValue("id")).isEqualTo(rawId);
156158
assertThat(paramSourceCaptor.getValue().getValue("value")).isEqualTo("vs. superman");
@@ -177,7 +179,7 @@ public void considersConfiguredWriteConverterForIdValueObjectsWhichReferencedInO
177179
additionalParameters.put(SqlIdentifier.quoted("DUMMYENTITYROOT"), rootIdValue);
178180
accessStrategy.insert(root, DummyEntityRoot.class, Identifier.from(additionalParameters));
179181

180-
verify(namedJdbcOperations).update(anyString(), paramSourceCaptor.capture(), any(KeyHolder.class));
182+
verify(namedJdbcOperations).update(anyString(), paramSourceCaptor.capture());
181183

182184
assertThat(paramSourceCaptor.getValue().getValue("id")).isEqualTo(rawId);
183185

@@ -191,6 +193,36 @@ public void considersConfiguredWriteConverterForIdValueObjectsWhichReferencedInO
191193
assertThat(paramSourceCaptor.getValue().getValue("DUMMYENTITYROOT")).isEqualTo(rawId);
192194
}
193195

196+
@Test // gh-933
197+
public void insertWithDefinedIdDoesNotRetrieveGeneratedKeys() {
198+
199+
Object generatedId = accessStrategy.insert(new DummyEntity(ORIGINAL_ID), DummyEntity.class, Identifier.from(additionalParameters));
200+
201+
assertThat(generatedId).isNull();
202+
203+
verify(namedJdbcOperations).update(eq("INSERT INTO \"DUMMY_ENTITY\" (\"ID\") VALUES (:id)"),
204+
paramSourceCaptor.capture());
205+
}
206+
207+
@Test // gh-933
208+
public void insertWithUndefinedIdRetrievesGeneratedKeys() {
209+
210+
when(namedJdbcOperations.update(any(), any(), any()))
211+
.then(invocation -> {
212+
213+
KeyHolder keyHolder = invocation.getArgument(2);
214+
keyHolder.getKeyList().add(singletonMap("ID", GENERATED_ID));
215+
return 1;
216+
});
217+
218+
Object generatedId = accessStrategy.insert(new DummyEntity(null), DummyEntity.class, Identifier.from(additionalParameters));
219+
220+
assertThat(generatedId).isEqualTo(GENERATED_ID);
221+
222+
verify(namedJdbcOperations).update(eq("INSERT INTO \"DUMMY_ENTITY\" VALUES ()"),
223+
paramSourceCaptor.capture(), any(KeyHolder.class));
224+
}
225+
194226
private DefaultDataAccessStrategy createAccessStrategyWithConverter(List<?> converters) {
195227
DelegatingDataAccessStrategy relationResolver = new DelegatingDataAccessStrategy();
196228

0 commit comments

Comments
 (0)