diff --git a/pom.xml b/pom.xml
index f0b2a42b23..a79c50d133 100644
--- a/pom.xml
+++ b/pom.xml
@@ -5,7 +5,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1323-in-with-tuple-SNAPSHOT
pom
Spring Data Relational Parent
diff --git a/spring-data-jdbc-distribution/pom.xml b/spring-data-jdbc-distribution/pom.xml
index 4626db4364..55b6d38479 100644
--- a/spring-data-jdbc-distribution/pom.xml
+++ b/spring-data-jdbc-distribution/pom.xml
@@ -14,7 +14,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1323-in-with-tuple-SNAPSHOT
../pom.xml
diff --git a/spring-data-jdbc/pom.xml b/spring-data-jdbc/pom.xml
index 266af71b96..69097d7caa 100644
--- a/spring-data-jdbc/pom.xml
+++ b/spring-data-jdbc/pom.xml
@@ -6,7 +6,7 @@
4.0.0
spring-data-jdbc
- 3.4.0-SNAPSHOT
+ 3.4.0-1323-in-with-tuple-SNAPSHOT
Spring Data JDBC
Spring Data module for JDBC repositories.
@@ -15,7 +15,7 @@
org.springframework.data
spring-data-relational-parent
- 3.4.0-SNAPSHOT
+ 3.4.0-1323-in-with-tuple-SNAPSHOT
diff --git a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java
index ef353497fa..3e7450e6ca 100644
--- a/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java
+++ b/spring-data-jdbc/src/main/java/org/springframework/data/jdbc/repository/query/StringBasedJdbcQuery.java
@@ -17,25 +17,24 @@
import static org.springframework.data.jdbc.repository.query.JdbcQueryExecution.*;
+import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
+import java.sql.JDBCType;
import java.sql.SQLType;
import java.util.ArrayList;
import java.util.Collection;
+import java.util.LinkedHashMap;
import java.util.List;
-import java.util.Map;
import java.util.function.Function;
import java.util.function.Supplier;
import org.springframework.beans.BeanInstantiationException;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.BeanFactory;
-import org.springframework.data.jdbc.core.convert.JdbcColumnTypes;
import org.springframework.data.jdbc.core.convert.JdbcConverter;
import org.springframework.data.jdbc.core.mapping.JdbcValue;
-import org.springframework.data.jdbc.support.JdbcUtil;
import org.springframework.data.relational.core.mapping.RelationalMappingContext;
import org.springframework.data.relational.repository.query.RelationalParameterAccessor;
-import org.springframework.data.relational.repository.query.RelationalParameters;
import org.springframework.data.relational.repository.query.RelationalParametersParameterAccessor;
import org.springframework.data.repository.query.Parameter;
import org.springframework.data.repository.query.Parameters;
@@ -52,7 +51,6 @@
import org.springframework.lang.Nullable;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
-import org.springframework.util.ConcurrentReferenceHashMap;
import org.springframework.util.ObjectUtils;
/**
@@ -72,7 +70,7 @@
*/
public class StringBasedJdbcQuery extends AbstractJdbcQuery {
- private static final String PARAMETER_NEEDS_TO_BE_NAMED = "For queries with named parameters you need to provide names for method parameters; Use @Param for query method parameters, or when on Java 8+ use the javac flag -parameters";
+ private static final String PARAMETER_NEEDS_TO_BE_NAMED = "For queries with named parameters you need to provide names for method parameters; Use @Param for query method parameters, or use the javac flag -parameters";
private final JdbcConverter converter;
private final RowMapperFactory rowMapperFactory;
private final SpelEvaluator spelEvaluator;
@@ -185,53 +183,103 @@ private JdbcQueryExecution> createJdbcQueryExecution(RelationalParameterAccess
private MapSqlParameterSource bindParameters(RelationalParameterAccessor accessor) {
- MapSqlParameterSource parameters = new MapSqlParameterSource();
-
Parameters, ?> bindableParameters = accessor.getBindableParameters();
+ MapSqlParameterSource parameters = new MapSqlParameterSource(
+ new LinkedHashMap<>(bindableParameters.getNumberOfParameters(), 1.0f));
for (Parameter bindableParameter : bindableParameters) {
- convertAndAddParameter(parameters, bindableParameter, accessor.getBindableValue(bindableParameter.getIndex()));
+
+ Object value = accessor.getBindableValue(bindableParameter.getIndex());
+ String parameterName = bindableParameter.getName()
+ .orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED));
+ JdbcParameters.JdbcParameter parameter = getQueryMethod().getParameters()
+ .getParameter(bindableParameter.getIndex());
+
+ JdbcValue jdbcValue = writeValue(value, parameter.getTypeInformation(), parameter);
+ SQLType jdbcType = jdbcValue.getJdbcType();
+
+ if (jdbcType == null) {
+ parameters.addValue(parameterName, jdbcValue.getValue());
+ } else {
+ parameters.addValue(parameterName, jdbcValue.getValue(), jdbcType.getVendorTypeNumber());
+ }
}
return parameters;
}
- private void convertAndAddParameter(MapSqlParameterSource parameters, Parameter p, Object value) {
+ private JdbcValue writeValue(@Nullable Object value, TypeInformation> typeInformation,
+ JdbcParameters.JdbcParameter parameter) {
+
+ if (value == null) {
+ return JdbcValue.of(value, parameter.getSqlType());
+ }
+
+ if (typeInformation.isCollectionLike() && value instanceof Collection> collection) {
+
+ TypeInformation> actualType = typeInformation.getActualType();
+
+ // tuple-binding
+ if (actualType != null && actualType.getType().isArray()) {
+
+ TypeInformation> nestedElementType = actualType.getRequiredActualType();
+ return writeCollection(collection, JDBCType.OTHER,
+ array -> writeArrayValue(parameter, array, nestedElementType));
+ }
+
+ // parameter expansion
+ return writeCollection(collection, parameter.getActualSqlType(),
+ it -> converter.writeJdbcValue(it, typeInformation.getRequiredActualType(), parameter.getActualSqlType()));
+ }
+
+ SQLType sqlType = parameter.getSqlType();
+ return converter.writeJdbcValue(value, typeInformation, sqlType);
+ }
- String parameterName = p.getName().orElseThrow(() -> new IllegalStateException(PARAMETER_NEEDS_TO_BE_NAMED));
+ private JdbcValue writeCollection(Collection> value, SQLType defaultType, Function