6

我正在使用 Spring JdbcTemplate,我被困在我有一个查询更新实际上是一个 int 数组的列的地方。数据库是 postgres 8.3.7。这是我正在使用的代码:

public int setUsersArray(int idUser, int idDevice, Collection<Integer> ids) {

    int update = -666;

    int[] tipi = new int[3];
    tipi[0] = java.sql.Types.INTEGER;
    tipi[1] = java.sql.Types.INTEGER;
    tipi[2] = java.sql.Types.ARRAY;

    try {
        update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
                ids, idUser, idDevice }, tipi);
    } catch (Exception e) {
        e.printStackTrace();
    }
    return update;
}

查询是“update table_name set array_column = ? where id_user = ? and id_device = ?”。我得到这个例外:

org.springframework.dao.DataIntegrityViolationException: PreparedStatementCallback; SQL [更新 acotel_msp.users_mau 设置 denied_sub_client = ? 哪里 id_users = ?和 id_mau = ?]; 列索引超出范围:4,列数:3。嵌套异常是 org.postgresql.util.PSQLException:列索引超出范围:4,列数:3。

引起:org.postgresql.util.PSQLException:列索引超出范围:4,列数:3。

我已经查看了 spring jdbc 模板文档,但找不到任何帮助,我会继续寻找,无论如何有人能指出我正确的方向吗?谢谢!

编辑 :

明明顺序错了,是我的错……

我尝试了你的两种解决方案,在第一种情况下我有这个:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; 错误的 SQL 语法 [更新用户集 denied_sub_client = ? 哪里 id_users = ?和 id_device = ?]; 嵌套异常是 org.postgresql.util.PSQLException: Cannot cast an instance of java.util.ArrayList to type Types.ARRAY

尝试第二种解决方案我有这个:

org.springframework.jdbc.BadSqlGrammarException: PreparedStatementCallback; 错误的 SQL 语法 [更新用户集 denied_sub_client = ? 哪里 id_users = ?和 id_device = ?]; 嵌套异常是 org.postgresql.util.PSQLException: Cannot cast an instance of [Ljava.lang.Object; 键入 Types.ARRAY

我想我需要一个 java.sql.Array 的实例,但是如何使用 JdbcTemplate 创建它?

4

7 回答 7

5

经过多次尝试后,我们决定使用一个小助手 ArraySqlValue 来为 Java Array Types 创建 Spring SqlValue 对象。

用法是这样的

jdbcTemplate.update(
                "UPDATE sometable SET arraycolumn = ?",
                ArraySqlValue.create(arrayValue))

ArraySqlValue 也可以在 MapSqlParameterSource 中与 NamedParameterJdbcTemplate 一起使用。

import static com.google.common.base.Preconditions.checkNotNull;

import java.sql.Array;
import java.sql.JDBCType;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.util.Locale;

import org.springframework.jdbc.core.StatementCreatorUtils;
import org.springframework.jdbc.support.SqlValue;

public class ArraySqlValue implements SqlValue {
    private final Object[] arr;
    private final String   dbTypeName;

    public static ArraySqlValue create(final Object[] arr) {
        return new ArraySqlValue(arr, determineDbTypeName(arr));
    }

    public static ArraySqlValue create(final Object[] arr, final String dbTypeName) {
        return new ArraySqlValue(arr, dbTypeName);
    }

    private ArraySqlValue(final Object[] arr, final String dbTypeName) {
        this.arr = checkNotNull(arr);
        this.dbTypeName = checkNotNull(dbTypeName);
    }

    @Override
    public void setValue(final PreparedStatement ps, final int paramIndex) throws SQLException {
        final Array arrayValue = ps.getConnection().createArrayOf(dbTypeName, arr);
        ps.setArray(paramIndex, arrayValue);
    }

    @Override
    public void cleanup() {}

    private static String determineDbTypeName(final Object[] arr) {
        // use Spring Utils similar to normal JdbcTemplate inner workings
        final int sqlParameterType =
            StatementCreatorUtils.javaTypeToSqlParameterType(arr.getClass().getComponentType());
        final JDBCType jdbcTypeToUse = JDBCType.valueOf(sqlParameterType);
        // lowercasing typename for Postgres
        final String typeNameToUse = jdbcTypeToUse.getName().toLowerCase(Locale.US);
        return typeNameToUse;
    }
}

此代码在公共领域提供

于 2019-03-28T12:53:40.667 回答
4
private static final String ARRAY_DATATYPE = "int4";
private static final String SQL_UPDATE = "UPDATE foo SET arr = ? WHERE d = ?";
final Integer[] existing = ...;
final DateTime dt = ...;

getJdbcTemplate().update(new PreparedStatementCreator() {
    @Override
    public PreparedStatement createPreparedStatement(final Connection con) throws SQLException {
        final PreparedStatement ret = con.prepareStatement(SQL_UPDATE);
        ret.setArray(1, con.createArrayOf(ARRAY_DATATYPE, existing));
        ret.setDate(2, new java.sql.Date(dt.getMillis()));
        return ret;
    }
});
于 2011-01-11T09:40:49.233 回答
3

这个解决方案是一种使用 postgreSQL 内置函数的解决方法,它肯定对我有用。

参考博客

1) 将字符串数组转换为逗号分隔的字符串

如果您使用的是 Java8,这很容易。其他选项在这里

String commaSeparatedString = String.join(",",stringArray); // Java8 feature

2) PostgreSQL 内建函数 string_to_array()

你可以在这里找到其他 postgreSQL 数组函数

// tableName ( name text, string_array_column_name text[] )

String query = "insert into tableName(name,string_array_column_name ) values(?, string_to_array(?,',') )";


int[] types = new int[] { Types.VARCHAR, Types.VARCHAR};

Object[] psParams = new Object[] {"Dhruvil Thaker",commaSeparatedString };

jdbcTemplate.batchUpdate(query, psParams ,types); // assuming you have jdbctemplate instance
于 2016-09-06T20:28:37.560 回答
1

参数类型和参数不匹配。

尝试更改参数类型顺序

int[] tipi = new int[3];
tipi[0] = java.sql.Types.ARRAY;
tipi[1] = java.sql.Types.INTEGER;
tipi[2] = java.sql.Types.INTEGER;

或使用

update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
                                ids.toArray(), idUser, idDevice })

看看它是否有效

于 2009-11-11T15:15:16.580 回答
1

http://valgogtech.blogspot.com/2009/02/passing-arrays-to-postgresql-database.html解释了如何创建 java.sql.Array postgresql 基本上 Array.getBaseTypeName 应该返回 int 并且 Array.toString 应该返回数组“{1,2,3}”格式的内容

创建数组后,您可以使用 PreparedStatementCreator中的preparedstatement.setArray(...)设置它,例如

jdbcTemplate.update(
    new PreparedStatementCreator() {
        public PreparedStatement createPreparedStatement(Connection connection) throws SQLException {

祝你好运 ..

于 2009-11-12T18:39:53.150 回答
1

到目前为止,我发现的最干净的方法是首先将 转换Collection为 anInteger[]然后使用 将Connection其转换为Array.

Integer[] idArray = ids.toArray(new Integer[0]);

Array idSqlArray = jdbcTemplate.execute(
        (Connection c) -> c.createArrayOf(JDBCType.INTEGER.getName(), idArray)
);

update = this.jdbcTemplate.update(setUsersArrayQuery, new Object[] {
                            idSqlArray, idUser, idDevice })

这是基于文档中的信息:https ://jdbc.postgresql.org/documentation/head/arrays.html

于 2019-02-01T06:59:21.977 回答
-1
java.sql.Array intArray = connection.createArrayOf("int", existing);
List<Object> values= new ArrayList<Object>();
values.add(intArray);
values.add(dt);
getJdbcTemplate().update(SQL_UPDATE,values);
于 2015-09-18T20:01:51.723 回答