如何将String []参数设置为本机查询? [英] How can I set a String[] parameter to a native query?

查看:90
本文介绍了如何将String []参数设置为本机查询?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

这是我的PostgreSQL函数:

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

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

  public String salvarGeometriaCaso0(String [] tuplas,FileDto arquivo){
查询查询=
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(); //函数返回一个Text,所以强制转换to String
}

上述代码失败,但有例外:

 错误]内部异常:org.postgresql.util.PSQLException:无法推断用于[Ljava实例]的SQL 
类型。 lang.String ;.
使用带有显式Types值的setObject()来指定要使用的类型。

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

解决方案

通过将String []类型的Java数组传递给 PreparedStatement.setObject(...)导致您报告的行为。似乎PgJDBC不接受Java数组作为 PreparedStatement.setObject()的参数,有或没有 Types.ARRAY 参数。



合规性



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

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

 通过调用方法
PreparedSatement.setObject,可以将Java数组作为输入参数传递。

虽然所有其余代码都引用了数组对象。它们是指Java数组中的数组吗?或者他们是指原始的本机Java数组,如 String []



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



该怎么办



尝试将EclipseLink更新为2.4,希望它能够使用< a href =http://docs.oracle.com/javase/tutorial/jdbc/basics/array.html>通过java.sql.Array对象将数组传递给JDBC的常用方法。 / p>

您可能还需要使用 @Array ,一个EclipseLink扩展。另请参见此论坛主题2.3版bug 361701



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

 数组sqlArray = conn.createArrayOf(text,strArray); 
pstmt.setArray(1,sqlArray);
pstmt.executeUpdate();

...其中 conn pstmt 分别是 java.sql.Connection PreparedStatement ,和 strArray 是一个 String [] 实例。



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



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






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

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

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


This is my PostgreSQL function:

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

It has a text[] parameter, and I want to pass a Java String[] to it from my JPQL:

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
}

The above code fails with the exception:

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.

so I'm not sure how to call my function from EclipseLink.

解决方案

Testing by passing a Java array of type String[] to PreparedStatement.setObject(...) results in the behaviour you report. It appears that PgJDBC doesn't accept a Java array as an argument to PreparedStatement.setObject(), with or without a Types.ARRAY parameter.

Compliance

The JDBC spec, 16.5 "Array Objects", suggests that the JDBC Array exists partly so the client doesn't have to copy big arrays into memory, they can be used by reference. I'm not too sure whether the JDBC driver is required to accept raw Java arrays as parameters. All the spec code refers to java.sql.Array and the spec makes it clear that arrays are mapped via the Array interface in Appendix B and elsewhere. In a quick search/reading I could find no mention of passing raw Java arrays other than byte[] as parameters or returning them as results.

However, in §16.5.4 the JDBC4.2 draft spec reads:

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

though all the rest of the code there refers to Array objects. Do they mean Array by "a Java array"? Or do they mean a raw native Java array like String[]?

It looks to me like clients are supposed to use the java.sql.Array interface via Connection.createArrayOf(...), so EclipseLink is probably doing the wrong thing.

What do do about it

Try updating EclipseLink to 2.4 in the hopes it uses the commonly specified method of passing arrays to JDBC via a java.sql.Array object.

You may also need to annotate the mapping with @Array, an EclipseLink extension. See also this forum thread re 2.3 and bug 361701.

It appears you may have to implement your own type handler for EclipseLink to override its behaviour. To correctly set an array parameter via PgJDBC you must use:

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

... where conn and pstmt are a java.sql.Connection and a PreparedStatement respectively, and strArray is a String[] instance.

See Custom data types in the eclipselink wiki.

On a side note, the use of a string type name to specify the array's data type in createArrayOf seems kind of insane given the existence of java.sql.Types. It makes portability much harder; the above code won't run on (say) Oracle, because Oracle wants VARCHAR not text as a type name.


Note: The unit test org/postgresql/test/jdbc2/ArrayTest.java has ArrayTest.testSetArray(), which at line 166 tests:

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

... however the type of arr is java.sql.Array, not int[]. It's a JDBC array type, not a regular Java array.

这篇关于如何将String []参数设置为本机查询?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆