10

这是我的 PostgreSQL 函数:

salvarArquivoGeometricoCasoZeroPOINT
(dimensao text,tableName text,tuplas text[],srid text)

它有一个text[]参数,我想String[]从我的 JPQL 向它传递一个 Java:

public String salvarGeometriaCaso0(String[] tuplas,FileDto arquivo){
        Query query =
        em().createNativeQuery("select 
salvarArquivoGeometricoCasoZeroPOINT(?1,?2,?3,?4)");
        query.setParameter(1,arquivo.getGeo());//String
        query.setParameter(2,arquivo.getTable());/String
        query.setParameter(3,tuplas);//String[]
        query.setParameter(4,arquivo.getSrid());//String
        return (String) query.getSingleResult();//function returns a Text, so cast to String
}

上面的代码失败,但有以下异常:

ERROR] Internal Exception: org.postgresql.util.PSQLException: Can not infer a SQL
type to use for an instance of [Ljava.lang.String;. 
Use setObject () with an explicit Types value to specify the type to use.

所以我不确定如何从 EclipseLink 调用我的函数。

4

4 回答 4

7

我很晚才回答。

这个解决方案是一种使用 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:15:43.567 回答
6

通过传递 String[] 类型的 Java 数组来进行测试,以PreparedStatement.setObject(...)产生您报告的行为。PgJDBC 似乎不接受 Java 数组作为参数PreparedStatement.setObject(),无论有无Types.ARRAY参数。

遵守

JDBC 规范16.5 "Array Objects"建议 JDBCArray部分存在,因此客户端不必将大数组复制到内存中,它们可以通过引用来使用。我不太确定 JDBC 驱动程序是否需要接受原始 Java 数组作为参数。所有规范代码都引用java.sql.Array并且规范清楚地表明数组是通过Array附录 B 和其他地方的接口映射的。在快速搜索/阅读中,除了作为参数或将它们作为结果返回之外,我没有提到传递原始 Java 数组。byte[]

但是,在 §16.5.4 中,JDBC4.2 草案规范如下:

A Java array may be passed as an input parameter by calling the method
PreparedSatement.setObject.

尽管那里的所有其余代码都引用了Array对象。它们是指Array“Java 数组”吗?还是他们的意思是原始的原生 Java 数组String[]

在我看来,客户端应该通过 使用java.sql.Array接口Connection.createArrayOf(...),所以 EclipseLink 可能做错了。

怎么办

尝试将 EclipseLink 更新到 2.4,希望它使用通过 java.sql.Array 对象将数组传递给 JDBC 的常用方法

您可能还需要使用@ArrayEclipseLink 扩展来注释映射。另请参阅此论坛主题 re 2.3错误 361701

看来您可能必须为 EclipseLink 实现自己的类型处理程序才能覆盖其行为。要通过 PgJDBC 正确设置数组参数,您必须使用:

    Array sqlArray = conn.createArrayOf("text", strArray);
    pstmt.setArray(1, sqlArray);
    pstmt.executeUpdate();

... 其中connandpstmt分别是 ajava.sql.Connection和 a PreparedStatement,andstrArray是一个String[]实例。

请参阅eclipselink wiki 中的自定义数据类型

在旁注中,使用字符串类型名称来指定数组的数据类型createArrayOf似乎有点疯狂,因为java.sql.Types. 它使便携性变得更加困难;上面的代码不会在(比如说)Oracle 上运行,因为 Oracle 不想VARCHAR作为text类型名称。


注意:单元测试org/postgresql/test/jdbc2/ArrayTest.javaArrayTest.testSetArray(),在第 166 行测试:

    pstmt.setObject(1, arr);
    pstmt.executeUpdate();

...但是类型arrjava.sql.Array,不是int[]。它是 JDBC 数组类型,而不是常规的 Java 数组。

于 2012-08-22T02:17:20.013 回答
1

似乎 EclipseLink 没有修复 @Craig Ringer 提到的错误 361701 。

将 String[] 作为参数传递的唯一方法是使用没有 EclipseLink 的 JDBC。检查代码。

Connection con = ConnectionHelper.getConnection();
        Array tArray = con.createArrayOf("text", tuplas);
        PreparedStatement pstm =
        con.prepareStatement("select salvarArquivoGeometricoCasoZeroPOINT(?,?,?,?)");
        pstm.setString(1,arquivo.getGeoType());
        pstm.setString(2,arquivo.getTable());
        pstm.setArray(3,tArray);
        pstm.setString(4,arquivo.getSrid());
        rs = pstm.executeQuery();

ConnectionHelper 这是我的 java.sql.Connection 类。

感谢你们的帮助:@Craig Ringer 和 @Matt Ball,谢谢。

于 2012-08-22T18:59:42.973 回答
0

jdbcTemplate.update我在不小心使用而不是时遇到了这个错误jdbcTemplate.batchUpdate

于 2019-03-11T14:59:06.673 回答