如何将String []参数设置为本机查询?

Ber*_*ale 9 java postgresql eclipselink jpql

这是我的PostgreSQL函数:

salvarArquivoGeometricoCasoZeroPOINT
(dimensao text,tableName text,tuplas text[],srid text)
Run Code Online (Sandbox Code Playgroud)

它有一个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
}
Run Code Online (Sandbox Code Playgroud)

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

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.
Run Code Online (Sandbox Code Playgroud)

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

Cra*_*ger 7

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

合规

JDBC规范16.5"数组对象"表明JDBC Array部分存在,因此客户端不必将大数组复制到内存中,它们可以通过引用使用.我不太确定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.
Run Code Online (Sandbox Code Playgroud)

虽然所有其余代码都引用了Array对象.它们是指Array"Java阵列"吗?或者它们是否意味着原始的本机Java数组String[]

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

怎么办呢

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

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

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

    Array sqlArray = conn.createArrayOf("text", strArray);
    pstmt.setArray(1, sqlArray);
    pstmt.executeUpdate();
Run Code Online (Sandbox Code Playgroud)

......其中connpstmt分别是a java.sql.Connection和a PreparedStatement,strArray是一个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();
Run Code Online (Sandbox Code Playgroud)

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


Dhr*_*ker 6

我很晚才回答.

这个解决方案是使用postgreSQL内置函数的一种解决方法,这对我来说绝对有用.

参考博客

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

如果您使用的是Java8,那就非常简单了.其他选择在这里

String commaSeparatedString = String.join(",",stringArray); // Java8 feature
Run Code Online (Sandbox Code Playgroud)

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
Run Code Online (Sandbox Code Playgroud)