Skip to content

Commit 0167b79

Browse files
committed
Consistently return empty array in case of empty batch arguments
Issue: SPR-17476 (cherry picked from commit 362c59c)
1 parent b462ca2 commit 0167b79

File tree

4 files changed

+69
-50
lines changed

4 files changed

+69
-50
lines changed

spring-jdbc/src/main/java/org/springframework/jdbc/core/BatchUpdateUtils.java

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -27,24 +27,29 @@
2727
* Mainly for internal use within the framework.
2828
*
2929
* @author Thomas Risberg
30+
* @author Juergen Hoeller
3031
* @since 3.0
3132
*/
3233
public abstract class BatchUpdateUtils {
3334

3435
public static int[] executeBatchUpdate(
35-
String sql, final List<Object[]> batchValues, final int[] columnTypes, JdbcOperations jdbcOperations) {
36+
String sql, final List<Object[]> batchArgs, final int[] columnTypes, JdbcOperations jdbcOperations) {
37+
38+
if (batchArgs.isEmpty()) {
39+
return new int[0];
40+
}
3641

3742
return jdbcOperations.batchUpdate(
3843
sql,
3944
new BatchPreparedStatementSetter() {
4045
@Override
4146
public void setValues(PreparedStatement ps, int i) throws SQLException {
42-
Object[] values = batchValues.get(i);
47+
Object[] values = batchArgs.get(i);
4348
setStatementParameters(values, ps, columnTypes);
4449
}
4550
@Override
4651
public int getBatchSize() {
47-
return batchValues.size();
52+
return batchArgs.size();
4853
}
4954
});
5055
}

spring-jdbc/src/main/java/org/springframework/jdbc/core/namedparam/NamedParameterBatchUpdateUtils.java

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2017 the original author or authors.
2+
* Copyright 2002-2018 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -28,15 +28,16 @@
2828
* Mainly for internal use within the framework.
2929
*
3030
* @author Thomas Risberg
31+
* @author Juergen Hoeller
3132
* @since 3.0
3233
*/
3334
public class NamedParameterBatchUpdateUtils extends BatchUpdateUtils {
3435

35-
public static int[] executeBatchUpdateWithNamedParameters(final ParsedSql parsedSql,
36-
final SqlParameterSource[] batchArgs, JdbcOperations jdbcOperations) {
36+
public static int[] executeBatchUpdateWithNamedParameters(
37+
final ParsedSql parsedSql, final SqlParameterSource[] batchArgs, JdbcOperations jdbcOperations) {
3738

38-
if (batchArgs.length <= 0) {
39-
return new int[] {0};
39+
if (batchArgs.length == 0) {
40+
return new int[0];
4041
}
4142

4243
String sqlToUse = NamedParameterUtils.substituteNamedParameters(parsedSql, batchArgs[0]);

spring-jdbc/src/test/java/org/springframework/jdbc/core/JdbcTemplateTests.java

Lines changed: 34 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,7 @@ private void doTestStrings(Integer fetchSize, Integer maxRows, Integer queryTime
191191
Object argument, JdbcTemplateCallback jdbcTemplateCallback) throws Exception {
192192

193193
String sql = "SELECT FORENAME FROM CUSTMR";
194-
String[] results = { "rod", "gary", " portia" };
194+
String[] results = {"rod", "gary", " portia"};
195195

196196
class StringHandler implements RowCallbackHandler {
197197
private List<String> list = new LinkedList<>();
@@ -490,8 +490,8 @@ public void testBatchUpdateWithNoBatchSupportAndSelect() throws Exception {
490490
@Test
491491
public void testBatchUpdateWithPreparedStatement() throws Exception {
492492
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
493-
final int[] ids = new int[] { 100, 200 };
494-
final int[] rowsAffected = new int[] { 1, 2 };
493+
final int[] ids = new int[] {100, 200};
494+
final int[] rowsAffected = new int[] {1, 2};
495495

496496
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
497497
mockDatabaseMetaData(true);
@@ -524,8 +524,8 @@ public int getBatchSize() {
524524
@Test
525525
public void testInterruptibleBatchUpdate() throws Exception {
526526
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
527-
final int[] ids = new int[] { 100, 200 };
528-
final int[] rowsAffected = new int[] { 1, 2 };
527+
final int[] ids = new int[] {100, 200};
528+
final int[] rowsAffected = new int[] {1, 2};
529529

530530
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
531531
mockDatabaseMetaData(true);
@@ -565,8 +565,8 @@ public boolean isBatchExhausted(int i) {
565565
@Test
566566
public void testInterruptibleBatchUpdateWithBaseClass() throws Exception {
567567
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
568-
final int[] ids = new int[] { 100, 200 };
569-
final int[] rowsAffected = new int[] { 1, 2 };
568+
final int[] ids = new int[] {100, 200};
569+
final int[] rowsAffected = new int[] {1, 2};
570570

571571
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
572572
mockDatabaseMetaData(true);
@@ -602,8 +602,8 @@ protected boolean setValuesIfAvailable(PreparedStatement ps, int i) throws SQLEx
602602
@Test
603603
public void testInterruptibleBatchUpdateWithBaseClassAndNoBatchSupport() throws Exception {
604604
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
605-
final int[] ids = new int[] { 100, 200 };
606-
final int[] rowsAffected = new int[] { 1, 2 };
605+
final int[] ids = new int[] {100, 200};
606+
final int[] rowsAffected = new int[] {1, 2};
607607

608608
given(this.preparedStatement.executeUpdate()).willReturn(rowsAffected[0], rowsAffected[1]);
609609
mockDatabaseMetaData(false);
@@ -639,8 +639,8 @@ protected boolean setValuesIfAvailable(PreparedStatement ps, int i) throws SQLEx
639639
@Test
640640
public void testBatchUpdateWithPreparedStatementAndNoBatchSupport() throws Exception {
641641
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
642-
final int[] ids = new int[] { 100, 200 };
643-
final int[] rowsAffected = new int[] { 1, 2 };
642+
final int[] ids = new int[] {100, 200};
643+
final int[] rowsAffected = new int[] {1, 2};
644644

645645
given(this.preparedStatement.executeUpdate()).willReturn(rowsAffected[0], rowsAffected[1]);
646646

@@ -670,7 +670,7 @@ public int getBatchSize() {
670670
@Test
671671
public void testBatchUpdateFails() throws Exception {
672672
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
673-
final int[] ids = new int[] { 100, 200 };
673+
final int[] ids = new int[] {100, 200};
674674
SQLException sqlException = new SQLException();
675675

676676
given(this.preparedStatement.executeBatch()).willThrow(sqlException);
@@ -701,6 +701,15 @@ public int getBatchSize() {
701701
}
702702
}
703703

704+
@Test
705+
public void testBatchUpdateWithEmptyList() throws Exception {
706+
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
707+
JdbcTemplate template = new JdbcTemplate(this.dataSource, false);
708+
709+
int[] actualRowsAffected = template.batchUpdate(sql, Collections.emptyList());
710+
assertTrue("executed 0 updates", actualRowsAffected.length == 0);
711+
}
712+
704713
@Test
705714
public void testBatchUpdateWithListOfObjectArrays() throws Exception {
706715
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
@@ -711,11 +720,9 @@ public void testBatchUpdateWithListOfObjectArrays() throws Exception {
711720

712721
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
713722
mockDatabaseMetaData(true);
714-
715723
JdbcTemplate template = new JdbcTemplate(this.dataSource, false);
716724

717725
int[] actualRowsAffected = template.batchUpdate(sql, ids);
718-
719726
assertTrue("executed 2 updates", actualRowsAffected.length == 2);
720727
assertEquals(rowsAffected[0], actualRowsAffected[0]);
721728
assertEquals(rowsAffected[1], actualRowsAffected[1]);
@@ -738,10 +745,9 @@ public void testBatchUpdateWithListOfObjectArraysPlusTypeInfo() throws Exception
738745

739746
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected);
740747
mockDatabaseMetaData(true);
741-
742748
this.template = new JdbcTemplate(this.dataSource, false);
743-
int[] actualRowsAffected = this.template.batchUpdate(sql, ids, sqlTypes);
744749

750+
int[] actualRowsAffected = this.template.batchUpdate(sql, ids, sqlTypes);
745751
assertTrue("executed 2 updates", actualRowsAffected.length == 2);
746752
assertEquals(rowsAffected[0], actualRowsAffected[0]);
747753
assertEquals(rowsAffected[1], actualRowsAffected[1]);
@@ -756,8 +762,8 @@ public void testBatchUpdateWithListOfObjectArraysPlusTypeInfo() throws Exception
756762
public void testBatchUpdateWithCollectionOfObjects() throws Exception {
757763
final String sql = "UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = ?";
758764
final List<Integer> ids = Arrays.asList(100, 200, 300);
759-
final int[] rowsAffected1 = new int[] { 1, 2 };
760-
final int[] rowsAffected2 = new int[] { 3 };
765+
final int[] rowsAffected1 = new int[] {1, 2};
766+
final int[] rowsAffected2 = new int[] {3};
761767

762768
given(this.preparedStatement.executeBatch()).willReturn(rowsAffected1, rowsAffected2);
763769
mockDatabaseMetaData(true);
@@ -780,50 +786,52 @@ public void testBatchUpdateWithCollectionOfObjects() throws Exception {
780786
}
781787

782788
@Test
783-
public void testCouldntGetConnectionForOperationOrExceptionTranslator() throws SQLException {
789+
public void testCouldNotGetConnectionForOperationOrExceptionTranslator() throws SQLException {
784790
SQLException sqlException = new SQLException("foo", "07xxx");
785791
this.dataSource = mock(DataSource.class);
786792
given(this.dataSource.getConnection()).willThrow(sqlException);
787793
JdbcTemplate template = new JdbcTemplate(this.dataSource, false);
788794
RowCountCallbackHandler rcch = new RowCountCallbackHandler();
795+
789796
this.thrown.expect(CannotGetJdbcConnectionException.class);
790797
this.thrown.expect(exceptionCause(sameInstance(sqlException)));
791798
template.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
792799
}
793800

794801
@Test
795-
public void testCouldntGetConnectionForOperationWithLazyExceptionTranslator() throws SQLException {
802+
public void testCouldNotGetConnectionForOperationWithLazyExceptionTranslator() throws SQLException {
796803
SQLException sqlException = new SQLException("foo", "07xxx");
797804
this.dataSource = mock(DataSource.class);
798805
given(this.dataSource.getConnection()).willThrow(sqlException);
799806
this.template = new JdbcTemplate();
800807
this.template.setDataSource(this.dataSource);
801808
this.template.afterPropertiesSet();
802809
RowCountCallbackHandler rcch = new RowCountCallbackHandler();
810+
803811
this.thrown.expect(CannotGetJdbcConnectionException.class);
804812
this.thrown.expect(exceptionCause(sameInstance(sqlException)));
805813
this.template.query("SELECT ID, FORENAME FROM CUSTMR WHERE ID < 3", rcch);
806814
}
807815

808816
@Test
809-
public void testCouldntGetConnectionInOperationWithExceptionTranslatorInitializedViaBeanProperty()
817+
public void testCouldNotGetConnectionInOperationWithExceptionTranslatorInitializedViaBeanProperty()
810818
throws SQLException {
811819

812-
doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(true);
820+
doTestCouldNotGetConnectionInOperationWithExceptionTranslatorInitialized(true);
813821
}
814822

815823
@Test
816-
public void testCouldntGetConnectionInOperationWithExceptionTranslatorInitializedInAfterPropertiesSet()
824+
public void testCouldNotGetConnectionInOperationWithExceptionTranslatorInitializedInAfterPropertiesSet()
817825
throws SQLException {
818826

819-
doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(false);
827+
doTestCouldNotGetConnectionInOperationWithExceptionTranslatorInitialized(false);
820828
}
821829

822830
/**
823831
* If beanProperty is true, initialize via exception translator bean property;
824832
* if false, use afterPropertiesSet().
825833
*/
826-
private void doTestCouldntGetConnectionInOperationWithExceptionTranslatorInitialized(boolean beanProperty)
834+
private void doTestCouldNotGetConnectionInOperationWithExceptionTranslatorInitialized(boolean beanProperty)
827835
throws SQLException {
828836

829837
SQLException sqlException = new SQLException("foo", "07xxx");
@@ -883,7 +891,7 @@ public void testPreparedStatementSetterFails() throws Exception {
883891
}
884892

885893
@Test
886-
public void testCouldntClose() throws Exception {
894+
public void testCouldNotClose() throws Exception {
887895
SQLException sqlException = new SQLException("bar");
888896
given(this.connection.createStatement()).willReturn(this.statement);
889897
given(this.resultSet.next()).willReturn(false);

spring-jdbc/src/test/java/org/springframework/jdbc/core/namedparam/NamedParameterJdbcTemplateTests.java

Lines changed: 20 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -418,12 +418,10 @@ public void testBatchUpdateWithPlainMap() throws Exception {
418418

419419
given(preparedStatement.executeBatch()).willReturn(rowsAffected);
420420
given(connection.getMetaData()).willReturn(databaseMetaData);
421+
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
421422

422-
JdbcTemplate template = new JdbcTemplate(dataSource, false);
423-
namedParameterTemplate = new NamedParameterJdbcTemplate(template);
424-
assertSame(template, namedParameterTemplate.getJdbcTemplate());
425-
426-
int[] actualRowsAffected = namedParameterTemplate.batchUpdate("UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
423+
int[] actualRowsAffected = namedParameterTemplate.batchUpdate(
424+
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
427425
assertTrue("executed 2 updates", actualRowsAffected.length == 2);
428426
assertEquals(rowsAffected[0], actualRowsAffected[0]);
429427
assertEquals(rowsAffected[1], actualRowsAffected[1]);
@@ -435,6 +433,17 @@ public void testBatchUpdateWithPlainMap() throws Exception {
435433
verify(connection, atLeastOnce()).close();
436434
}
437435

436+
@Test
437+
public void testBatchUpdateWithEmptyMap() throws Exception {
438+
@SuppressWarnings("unchecked")
439+
final Map<String, Integer>[] ids = new Map[0];
440+
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
441+
442+
int[] actualRowsAffected = namedParameterTemplate.batchUpdate(
443+
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
444+
assertTrue("executed 0 updates", actualRowsAffected.length == 0);
445+
}
446+
438447
@Test
439448
public void testBatchUpdateWithSqlParameterSource() throws Exception {
440449
SqlParameterSource[] ids = new SqlParameterSource[2];
@@ -444,12 +453,10 @@ public void testBatchUpdateWithSqlParameterSource() throws Exception {
444453

445454
given(preparedStatement.executeBatch()).willReturn(rowsAffected);
446455
given(connection.getMetaData()).willReturn(databaseMetaData);
456+
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
447457

448-
JdbcTemplate template = new JdbcTemplate(dataSource, false);
449-
namedParameterTemplate = new NamedParameterJdbcTemplate(template);
450-
assertSame(template, namedParameterTemplate.getJdbcTemplate());
451-
452-
int[] actualRowsAffected = namedParameterTemplate.batchUpdate("UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
458+
int[] actualRowsAffected = namedParameterTemplate.batchUpdate(
459+
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
453460
assertTrue("executed 2 updates", actualRowsAffected.length == 2);
454461
assertEquals(rowsAffected[0], actualRowsAffected[0]);
455462
assertEquals(rowsAffected[1], actualRowsAffected[1]);
@@ -470,12 +477,10 @@ public void testBatchUpdateWithSqlParameterSourcePlusTypeInfo() throws Exception
470477

471478
given(preparedStatement.executeBatch()).willReturn(rowsAffected);
472479
given(connection.getMetaData()).willReturn(databaseMetaData);
480+
namedParameterTemplate = new NamedParameterJdbcTemplate(new JdbcTemplate(dataSource, false));
473481

474-
JdbcTemplate template = new JdbcTemplate(dataSource, false);
475-
namedParameterTemplate = new NamedParameterJdbcTemplate(template);
476-
assertSame(template, namedParameterTemplate.getJdbcTemplate());
477-
478-
int[] actualRowsAffected = namedParameterTemplate.batchUpdate("UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
482+
int[] actualRowsAffected = namedParameterTemplate.batchUpdate(
483+
"UPDATE NOSUCHTABLE SET DATE_DISPATCHED = SYSDATE WHERE ID = :id", ids);
479484
assertTrue("executed 2 updates", actualRowsAffected.length == 2);
480485
assertEquals(rowsAffected[0], actualRowsAffected[0]);
481486
assertEquals(rowsAffected[1], actualRowsAffected[1]);

0 commit comments

Comments
 (0)