Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -161,25 +161,29 @@ public StatementSpec param(@Nullable Object value) {

@Override
public StatementSpec param(int jdbcIndex, @Nullable Object value) {
addIndexedParam(this.indexedParams, jdbcIndex, value);
return this;
}

private static void addIndexedParam(List<@Nullable Object> indexedParams, int jdbcIndex, @Nullable Object value) {

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sbrannen I make this util method as static to avoid misusing this.indexedParams, is it recommended?

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, making it static is a good call, but please move addIndexedParam() and validateIndexedParamValue() below statementCreatorForIndexedParamsWithKeys().

if (jdbcIndex < 1) {
throw new IllegalArgumentException("Invalid JDBC index: needs to start at 1");
}
validateIndexedParamValue(value);
int index = jdbcIndex - 1;
int size = this.indexedParams.size();
int size = indexedParams.size();
if (index < size) {
this.indexedParams.set(index, value);
indexedParams.set(index, value);
}
else {
for (int i = size; i < index; i++) {
this.indexedParams.add(null);
indexedParams.add(null);
}
this.indexedParams.add(value);
indexedParams.add(value);
}
return this;
}

private void validateIndexedParamValue(@Nullable Object value) {
private static void validateIndexedParamValue(@Nullable Object value) {
if (value instanceof Iterable) {
throw new IllegalArgumentException("Invalid positional parameter value of type Iterable (" +
value.getClass().getSimpleName() +
Expand Down Expand Up @@ -355,12 +359,28 @@ public BatchSpec param(@Nullable Object value) {
return this;
}

@Override
public BatchSpec param(int jdbcIndex, @Nullable Object value) {
addIndexedParam(this.currentIndexedParams, jdbcIndex, value);
return this;
}

@Override
public BatchSpec param(int jdbcIndex, @Nullable Object value, int sqlType) {
return param(jdbcIndex, new SqlParameterValue(sqlType, value));
}

@Override
public BatchSpec param(String name, @Nullable Object value) {
this.currentNamedParams.addValue(name, value);
return this;
}

@Override
public BatchSpec param(String name, @Nullable Object value, int sqlType) {
return param(name, new SqlParameterValue(sqlType, value));
}

@Override
public BatchSpec params(Object... values) {
Collections.addAll(this.currentIndexedParams, values);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -398,6 +398,27 @@ interface BatchSpec {
*/
BatchSpec param(@Nullable Object value);

/**
* Bind a positional JDBC statement parameter for "?" placeholder resolution
* by explicit JDBC statement parameter index.
* @param jdbcIndex the JDBC-style index (starting with 1)
* @param value the parameter value to bind
* @return this batch specification (for chaining)
* @see java.sql.PreparedStatement#setObject(int, Object)
*/
BatchSpec param(int jdbcIndex, @Nullable Object value);

/**
* Bind a positional JDBC statement parameter for "?" placeholder resolution
* by explicit JDBC statement parameter index.
* @param jdbcIndex the JDBC-style index (starting with 1)
* @param value the parameter value to bind
* @param sqlType the associated SQL type (see {@link java.sql.Types})
* @return this batch specification (for chaining)
* @see java.sql.PreparedStatement#setObject(int, Object, int)
*/
BatchSpec param(int jdbcIndex, @Nullable Object value, int sqlType);

/**
* Bind a named parameter for the current batch entry.
* @param name the parameter name
Expand All @@ -407,6 +428,16 @@ interface BatchSpec {
*/
BatchSpec param(String name, @Nullable Object value);

/**
* Bind a named parameter for the current batch entry.
* @param name the parameter name
* @param value the parameter value to bind
* @param sqlType the associated SQL type (see {@link java.sql.Types})
* @return this batch specification (for chaining)
* @see java.sql.PreparedStatement#setObject(int, Object, int)
*/
BatchSpec param(String name, @Nullable Object value, int sqlType);

/**
* Bind a var-args list of positional parameters for the current batch entry.
* @param values the parameter values to bind
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@

/**
* @author Juergen Hoeller
* @author Yanming Zhou
* @since 6.1
*/
class JdbcClientIndexedParameterTests {
Expand Down Expand Up @@ -322,6 +323,23 @@ void update() throws SQLException {
verify(connection).close();
}

@Test
void batchUpdate() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_INDEXED_PARAMETERS).batch()
.param(1, 1)
.param(2, 1)
.add().update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_INDEXED_PARAMETERS);
verify(preparedStatement).setObject(1, 1);
verify(preparedStatement).setObject(2, 1);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void updateWithTypedParameters() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);
Expand All @@ -338,6 +356,40 @@ void updateWithTypedParameters() throws SQLException {
verify(connection).close();
}

@Test
void batchUpdateWithTypedParameters() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_INDEXED_PARAMETERS).batch()
.param(1, new SqlParameterValue(Types.DECIMAL, 1))
.param(2, new SqlParameterValue(Types.INTEGER, 1))
.add().update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_INDEXED_PARAMETERS);
verify(preparedStatement).setObject(1, 1, Types.DECIMAL);
verify(preparedStatement).setObject(2, 1, Types.INTEGER);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void batchUpdateWithParametersAndSqlType() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_INDEXED_PARAMETERS).batch()
.param(1, 1, Types.DECIMAL)
.param(2, 1, Types.INTEGER)
.add().update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_INDEXED_PARAMETERS);
verify(preparedStatement).setObject(1, 1, Types.DECIMAL);
verify(preparedStatement).setObject(2, 1, Types.INTEGER);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void updateWithGeneratedKeys() throws SQLException {
given(resultSetMetaData.getColumnCount()).willReturn(1);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@

package org.springframework.jdbc.core.simple;

import java.sql.Types;
import java.util.List;
import java.util.Map;

Expand Down Expand Up @@ -165,6 +166,34 @@ void batchUpdateWithIndexedParameters() {
assertUser(2, "John", "Doe");
}

@Test
void batchUpdateWithJdbcIndexParameters() {
int[] rowsAffected = this.jdbcClient.sql(INSERT_WITH_JDBC_PARAMS)
.batch()
.param(2, "Smith").param(1, "Jane").add()
.param(2, "Doe").param(1, "John")
.update();

assertThat(rowsAffected).containsExactly(1, 1);
assertNumUsers(3);
assertUser(1, "Jane", "Smith");
assertUser(2, "John", "Doe");
}

@Test
void batchUpdateWithJdbcIndexParametersAndSqlType() {
int[] rowsAffected = this.jdbcClient.sql(INSERT_WITH_JDBC_PARAMS)
.batch()
.param(2, "Smith", Types.VARCHAR).param(1, "Jane", Types.VARCHAR).add()
.param(2, "Doe", Types.VARCHAR).param(1, "John", Types.VARCHAR)
.update();

assertThat(rowsAffected).containsExactly(1, 1);
assertNumUsers(3);
assertUser(1, "Jane", "Smith");
assertUser(2, "John", "Doe");
}

@Test
void batchUpdateWithNamedParameters() {
int[] rowsAffected = this.jdbcClient.sql(INSERT_WITH_NAMED_PARAMS)
Expand All @@ -179,6 +208,20 @@ void batchUpdateWithNamedParameters() {
assertUser(2, "John", "Doe");
}

@Test
void batchUpdateWithNamedParametersAndSqlType() {
int[] rowsAffected = this.jdbcClient.sql(INSERT_WITH_NAMED_PARAMS)
.batch()
.param("firstName", "Jane", Types.VARCHAR).param("lastName", "Smith", Types.VARCHAR).add()
.param("firstName", "John", Types.VARCHAR).param("lastName", "Doe", Types.VARCHAR)
.update();

assertThat(rowsAffected).containsExactly(1, 1);
assertNumUsers(3);
assertUser(1, "Jane", "Smith");
assertUser(2, "John", "Doe");
}

@Test
void batchUpdateWithIndividualIndexedParameters() {
int[] rowsAffected = this.jdbcClient.sql(INSERT_WITH_JDBC_PARAMS)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@

/**
* @author Juergen Hoeller
* @author Yanming Zhou
* @since 6.1
*/
class JdbcClientNamedParameterTests {
Expand Down Expand Up @@ -389,6 +390,22 @@ void update() throws SQLException {
verify(connection).close();
}

@Test
void batchUpdate() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_NAMED_PARAMETERS).batch()
.param("perfId", 1).param("priceId", 1).add()
.update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
verify(preparedStatement).setObject(1, 1);
verify(preparedStatement).setObject(2, 1);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void updateWithTypedParameters() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);
Expand All @@ -405,6 +422,42 @@ void updateWithTypedParameters() throws SQLException {
verify(connection).close();
}

@Test
void batchUpdateWithTypedParameters() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_NAMED_PARAMETERS).batch()
.param("perfId", new SqlParameterValue(Types.DECIMAL, 1))
.param("priceId", new SqlParameterValue(Types.INTEGER, 1))
.add()
.update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
verify(preparedStatement).setObject(1, 1, Types.DECIMAL);
verify(preparedStatement).setObject(2, 1, Types.INTEGER);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void batchUpdateWithParametersAndSqlType() throws SQLException {
given(preparedStatement.executeUpdate()).willReturn(1);

int[] rowsAffected = client.sql(UPDATE_NAMED_PARAMETERS).batch()
.param("perfId", 1, Types.DECIMAL)
.param("priceId", 1, Types.INTEGER)
.add()
.update();

assertThat(rowsAffected).containsExactly(1);
verify(connection).prepareStatement(UPDATE_NAMED_PARAMETERS_PARSED);
verify(preparedStatement).setObject(1, 1, Types.DECIMAL);
verify(preparedStatement).setObject(2, 1, Types.INTEGER);
verify(preparedStatement).close();
verify(connection).close();
}

@Test
void updateWithGeneratedKeys() throws SQLException {
given(resultSetMetaData.getColumnCount()).willReturn(1);
Expand Down
Loading