From 3fed2ec3a198103586e9ca28b8965c2dd8714af4 Mon Sep 17 00:00:00 2001 From: Juergen Hoeller Date: Thu, 13 Jul 2023 00:28:32 +0200 Subject: [PATCH] Add common SqlValue implementation for JDBC Array creation Closes gh-1850 --- .../jdbc/support/SqlArrayValue.java | 79 +++++++++++++++++++ .../jdbc/support/SqlArrayValueTests.java | 62 +++++++++++++++ 2 files changed, 141 insertions(+) create mode 100644 spring-jdbc/src/main/java/org/springframework/jdbc/support/SqlArrayValue.java create mode 100644 spring-jdbc/src/test/java/org/springframework/jdbc/support/SqlArrayValueTests.java diff --git a/spring-jdbc/src/main/java/org/springframework/jdbc/support/SqlArrayValue.java b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SqlArrayValue.java new file mode 100644 index 00000000000..101169eeea2 --- /dev/null +++ b/spring-jdbc/src/main/java/org/springframework/jdbc/support/SqlArrayValue.java @@ -0,0 +1,79 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.support; + +import java.sql.Array; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.springframework.dao.DataAccessResourceFailureException; +import org.springframework.lang.Nullable; +import org.springframework.util.Assert; + +/** + * Common {@link SqlValue} implementation for JDBC {@link Array} creation + * based on the JDBC 4 {@link java.sql.Connection#createArrayOf} method. + * + *

Also serves as a template for custom {@link SqlValue} implementations. + * + * @author Juergen Hoeller + * @author Philippe Marschall + * @since 6.1 + */ +public class SqlArrayValue implements SqlValue { + + private final String typeName; + + private final Object[] elements; + + @Nullable + private Array array; + + + /** + * Create a new {@code SqlArrayValue} for the given type name and elements. + * @param typeName the SQL name of the type the elements of the array map to + * @param elements the elements to populate the {@code Array} object with + * @see java.sql.Connection#createArrayOf + */ + public SqlArrayValue(String typeName, Object[] elements) { + Assert.notNull(typeName, "Type name must not be null"); + Assert.notNull(elements, "Elements array must not be null"); + this.typeName = typeName; + this.elements = elements; + } + + + @Override + public void setValue(PreparedStatement ps, int paramIndex) throws SQLException { + this.array = ps.getConnection().createArrayOf(this.typeName, this.elements); + ps.setArray(paramIndex, this.array); + } + + @Override + public void cleanup() { + if (this.array != null) { + try { + this.array.free(); + } + catch (SQLException ex) { + throw new DataAccessResourceFailureException("Could not free Array object", ex); + } + } + } + +} diff --git a/spring-jdbc/src/test/java/org/springframework/jdbc/support/SqlArrayValueTests.java b/spring-jdbc/src/test/java/org/springframework/jdbc/support/SqlArrayValueTests.java new file mode 100644 index 00000000000..9207591dbfd --- /dev/null +++ b/spring-jdbc/src/test/java/org/springframework/jdbc/support/SqlArrayValueTests.java @@ -0,0 +1,62 @@ +/* + * Copyright 2002-2023 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * https://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.jdbc.support; + +import java.sql.Array; +import java.sql.Connection; +import java.sql.PreparedStatement; +import java.sql.SQLException; + +import org.junit.jupiter.api.Test; + +import static org.mockito.BDDMockito.given; +import static org.mockito.BDDMockito.mock; +import static org.mockito.BDDMockito.verify; + +/** + * Tests for {@link SqlArrayValue}. + * + * @author Philippe Marschall + * @since 6.1 + */ +public class SqlArrayValueTests { + + private final Connection con = mock(); + + private final PreparedStatement ps = mock(); + + private final Array arr = mock(); + + private final Object[] elements = new Object[] {1, 2, 3}; + + private final SqlArrayValue sqlArrayValue = new SqlArrayValue("smallint", elements); + + + @Test + public void setValue() throws SQLException { + given(this.ps.getConnection()).willReturn(this.con); + given(this.con.createArrayOf("smallint", elements)).willReturn(this.arr); + + int paramIndex = 42; + this.sqlArrayValue.setValue(this.ps, paramIndex); + verify(ps).setArray(paramIndex, arr); + + this.sqlArrayValue.cleanup(); + verify(this.arr).free(); + } + +}