Skip to content

Commit 01fc1ee

Browse files
committed
Introduce update variant with KeyHolder and explicit key column names
Closes gh-31607
1 parent 510caad commit 01fc1ee

File tree

5 files changed

+129
-17
lines changed

5 files changed

+129
-17
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/DefaultJdbcClient.java

Lines changed: 22 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -218,15 +218,15 @@ public void query(RowCallbackHandler rch) {
218218
namedParamOps.query(this.sql, this.namedParamSource, rch);
219219
}
220220
else {
221-
classicOps.query(getPreparedStatementCreatorForIndexedParams(), rch);
221+
classicOps.query(statementCreatorForIndexedParams(), rch);
222222
}
223223
}
224224

225225
@Override
226226
public <T> T query(ResultSetExtractor<T> rse) {
227227
T result = (useNamedParams() ?
228228
namedParamOps.query(this.sql, this.namedParamSource, rse) :
229-
classicOps.query(getPreparedStatementCreatorForIndexedParams(), rse));
229+
classicOps.query(statementCreatorForIndexedParams(), rse));
230230
Assert.state(result != null, "No result from ResultSetExtractor");
231231
return result;
232232
}
@@ -235,14 +235,21 @@ public <T> T query(ResultSetExtractor<T> rse) {
235235
public int update() {
236236
return (useNamedParams() ?
237237
namedParamOps.update(this.sql, this.namedParamSource) :
238-
classicOps.update(getPreparedStatementCreatorForIndexedParams()));
238+
classicOps.update(statementCreatorForIndexedParams()));
239239
}
240240

241241
@Override
242242
public int update(KeyHolder generatedKeyHolder) {
243243
return (useNamedParams() ?
244244
namedParamOps.update(this.sql, this.namedParamSource, generatedKeyHolder) :
245-
classicOps.update(getPreparedStatementCreatorForIndexedParams(true), generatedKeyHolder));
245+
classicOps.update(statementCreatorForIndexedParamsWithKeys(null), generatedKeyHolder));
246+
}
247+
248+
@Override
249+
public int update(KeyHolder generatedKeyHolder, String... keyColumnNames) {
250+
return (useNamedParams() ?
251+
namedParamOps.update(this.sql, this.namedParamSource, generatedKeyHolder, keyColumnNames) :
252+
classicOps.update(statementCreatorForIndexedParamsWithKeys(keyColumnNames), generatedKeyHolder));
246253
}
247254

248255
private boolean useNamedParams() {
@@ -257,14 +264,19 @@ private boolean useNamedParams() {
257264
return hasNamedParams;
258265
}
259266

260-
private PreparedStatementCreator getPreparedStatementCreatorForIndexedParams() {
261-
return getPreparedStatementCreatorForIndexedParams(false);
267+
private PreparedStatementCreator statementCreatorForIndexedParams() {
268+
return new PreparedStatementCreatorFactory(this.sql).newPreparedStatementCreator(this.indexedParams);
262269
}
263270

264-
private PreparedStatementCreator getPreparedStatementCreatorForIndexedParams(boolean returnGeneratedKeys) {
265-
PreparedStatementCreatorFactory factory = new PreparedStatementCreatorFactory(this.sql);
266-
factory.setReturnGeneratedKeys(returnGeneratedKeys);
267-
return factory.newPreparedStatementCreator(this.indexedParams);
271+
private PreparedStatementCreator statementCreatorForIndexedParamsWithKeys(@Nullable String[] keyColumnNames) {
272+
PreparedStatementCreatorFactory pscf = new PreparedStatementCreatorFactory(this.sql);
273+
if (keyColumnNames != null) {
274+
pscf.setGeneratedKeysColumnNames(keyColumnNames);
275+
}
276+
else {
277+
pscf.setReturnGeneratedKeys(true);
278+
}
279+
return pscf.newPreparedStatementCreator(this.indexedParams);
268280
}
269281

270282

spring-jdbc/src/main/java/org/springframework/jdbc/core/simple/JdbcClient.java

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -288,6 +288,16 @@ interface StatementSpec {
288288
* @see java.sql.PreparedStatement#executeUpdate()
289289
*/
290290
int update(KeyHolder generatedKeyHolder);
291+
292+
/**
293+
* Execute the provided SQL statement as an update.
294+
* @param generatedKeyHolder a KeyHolder that will hold the generated keys
295+
* (typically a {@link org.springframework.jdbc.support.GeneratedKeyHolder})
296+
* @param keyColumnNames names of the columns that will have keys generated for them
297+
* @return the number of rows affected
298+
* @see java.sql.PreparedStatement#executeUpdate()
299+
*/
300+
int update(KeyHolder generatedKeyHolder, String... keyColumnNames);
291301
}
292302

293303

spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/JdbcClientIndexedParameterTests.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -339,7 +339,7 @@ public void updateWithTypedParameters() throws SQLException {
339339
}
340340

341341
@Test
342-
public void updateAndGeneratedKeys() throws SQLException {
342+
public void updateWithGeneratedKeys() throws SQLException {
343343
given(resultSetMetaData.getColumnCount()).willReturn(1);
344344
given(resultSetMetaData.getColumnLabel(1)).willReturn("1");
345345
given(resultSet.getMetaData()).willReturn(resultSetMetaData);
@@ -362,4 +362,28 @@ public void updateAndGeneratedKeys() throws SQLException {
362362
verify(connection).close();
363363
}
364364

365+
@Test
366+
public void updateWithGeneratedKeysAndKeyColumnNames() throws SQLException {
367+
given(resultSetMetaData.getColumnCount()).willReturn(1);
368+
given(resultSetMetaData.getColumnLabel(1)).willReturn("1");
369+
given(resultSet.getMetaData()).willReturn(resultSetMetaData);
370+
given(resultSet.next()).willReturn(true, false);
371+
given(resultSet.getObject(1)).willReturn(11);
372+
given(preparedStatement.executeUpdate()).willReturn(1);
373+
given(preparedStatement.getGeneratedKeys()).willReturn(resultSet);
374+
given(connection.prepareStatement(INSERT_GENERATE_KEYS, new String[] {"id"}))
375+
.willReturn(preparedStatement);
376+
377+
KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
378+
int rowsAffected = client.sql(INSERT_GENERATE_KEYS).param("rod").update(generatedKeyHolder, "id");
379+
380+
assertThat(rowsAffected).isEqualTo(1);
381+
assertThat(generatedKeyHolder.getKeyList()).hasSize(1);
382+
assertThat(generatedKeyHolder.getKey()).isEqualTo(11);
383+
verify(preparedStatement).setString(1, "rod");
384+
verify(resultSet).close();
385+
verify(preparedStatement).close();
386+
verify(connection).close();
387+
}
388+
365389
}

spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/JdbcClientIntegrationTests.java

Lines changed: 47 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -34,16 +34,18 @@
3434
* Integration tests for {@link JdbcClient} using an embedded H2 database.
3535
*
3636
* @author Sam Brannen
37+
* @author Juergen Hoeller
3738
* @since 6.1
3839
* @see JdbcClientIndexedParameterTests
3940
* @see JdbcClientNamedParameterTests
4041
*/
4142
class JdbcClientIntegrationTests {
4243

44+
private static final String INSERT_WITH_JDBC_PARAMS =
45+
"INSERT INTO users (first_name, last_name) VALUES(?, ?)";
46+
4347
private static final String INSERT_WITH_NAMED_PARAMS =
4448
"INSERT INTO users (first_name, last_name) VALUES(:firstName, :lastName)";
45-
private static final String INSERT_WITH_POSITIONAL_PARAMS =
46-
"INSERT INTO users (first_name, last_name) VALUES(?, ?)";
4749

4850

4951
private final EmbeddedDatabase embeddedDatabase =
@@ -66,15 +68,16 @@ void shutdownDatabase() {
6668
this.embeddedDatabase.shutdown();
6769
}
6870

71+
6972
@Test
70-
void updateWithGeneratedKeysAndPositionalParameters() {
73+
void updateWithGeneratedKeys() {
7174
int expectedId = 2;
7275
String firstName = "Jane";
7376
String lastName = "Smith";
7477

7578
KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
7679

77-
int rowsAffected = this.jdbcClient.sql(INSERT_WITH_POSITIONAL_PARAMS)
80+
int rowsAffected = this.jdbcClient.sql(INSERT_WITH_JDBC_PARAMS)
7881
.params(firstName, lastName)
7982
.update(generatedKeyHolder);
8083

@@ -85,7 +88,25 @@ void updateWithGeneratedKeysAndPositionalParameters() {
8588
}
8689

8790
@Test
88-
void updateWithGeneratedKeysAndNamedParameters() {
91+
void updateWithGeneratedKeysAndKeyColumnNames() {
92+
int expectedId = 2;
93+
String firstName = "Jane";
94+
String lastName = "Smith";
95+
96+
KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
97+
98+
int rowsAffected = this.jdbcClient.sql(INSERT_WITH_JDBC_PARAMS)
99+
.params(firstName, lastName)
100+
.update(generatedKeyHolder, "id");
101+
102+
assertThat(rowsAffected).isEqualTo(1);
103+
assertThat(generatedKeyHolder.getKey()).isEqualTo(expectedId);
104+
assertNumUsers(2);
105+
assertUser(expectedId, firstName, lastName);
106+
}
107+
108+
@Test
109+
void updateWithGeneratedKeysUsingNamedParameters() {
89110
int expectedId = 2;
90111
String firstName = "Jane";
91112
String lastName = "Smith";
@@ -103,6 +124,26 @@ void updateWithGeneratedKeysAndNamedParameters() {
103124
assertUser(expectedId, firstName, lastName);
104125
}
105126

127+
@Test
128+
void updateWithGeneratedKeysAndKeyColumnNamesUsingNamedParameters() {
129+
int expectedId = 2;
130+
String firstName = "Jane";
131+
String lastName = "Smith";
132+
133+
KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
134+
135+
int rowsAffected = this.jdbcClient.sql(INSERT_WITH_NAMED_PARAMS)
136+
.param("firstName", firstName)
137+
.param("lastName", lastName)
138+
.update(generatedKeyHolder, "id");
139+
140+
assertThat(rowsAffected).isEqualTo(1);
141+
assertThat(generatedKeyHolder.getKey()).isEqualTo(expectedId);
142+
assertNumUsers(2);
143+
assertUser(expectedId, firstName, lastName);
144+
}
145+
146+
106147
private void assertNumUsers(long count) {
107148
long numUsers = this.jdbcClient.sql("select count(id) from users").query(Long.class).single();
108149
assertThat(numUsers).isEqualTo(count);
@@ -113,6 +154,7 @@ private void assertUser(long id, String firstName, String lastName) {
113154
assertThat(user).isEqualTo(new User(id, firstName, lastName));
114155
}
115156

157+
116158
record User(long id, String firstName, String lastName) {};
117159

118160
}

spring-jdbc/src/test/java/org/springframework/jdbc/core/simple/JdbcClientNamedParameterTests.java

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -406,7 +406,7 @@ void updateWithTypedParameters() throws SQLException {
406406
}
407407

408408
@Test
409-
void updateAndGeneratedKeys() throws SQLException {
409+
void updateWithGeneratedKeys() throws SQLException {
410410
given(resultSetMetaData.getColumnCount()).willReturn(1);
411411
given(resultSetMetaData.getColumnLabel(1)).willReturn("1");
412412
given(resultSet.getMetaData()).willReturn(resultSetMetaData);
@@ -429,4 +429,28 @@ void updateAndGeneratedKeys() throws SQLException {
429429
verify(connection).close();
430430
}
431431

432+
@Test
433+
public void updateWithGeneratedKeysAndKeyColumnNames() throws SQLException {
434+
given(resultSetMetaData.getColumnCount()).willReturn(1);
435+
given(resultSetMetaData.getColumnLabel(1)).willReturn("1");
436+
given(resultSet.getMetaData()).willReturn(resultSetMetaData);
437+
given(resultSet.next()).willReturn(true, false);
438+
given(resultSet.getObject(1)).willReturn(11);
439+
given(preparedStatement.executeUpdate()).willReturn(1);
440+
given(preparedStatement.getGeneratedKeys()).willReturn(resultSet);
441+
given(connection.prepareStatement(INSERT_GENERATE_KEYS_PARSED, new String[] {"id"}))
442+
.willReturn(preparedStatement);
443+
444+
KeyHolder generatedKeyHolder = new GeneratedKeyHolder();
445+
int rowsAffected = client.sql(INSERT_GENERATE_KEYS).param("name", "rod").update(generatedKeyHolder, "id");
446+
447+
assertThat(rowsAffected).isEqualTo(1);
448+
assertThat(generatedKeyHolder.getKeyList()).hasSize(1);
449+
assertThat(generatedKeyHolder.getKey()).isEqualTo(11);
450+
verify(preparedStatement).setString(1, "rod");
451+
verify(resultSet).close();
452+
verify(preparedStatement).close();
453+
verify(connection).close();
454+
}
455+
432456
}

0 commit comments

Comments
 (0)