在 Java 中创建一个 bytea 数组以传递给 Postgresql 存储过程

Posted

技术标签:

【中文标题】在 Java 中创建一个 bytea 数组以传递给 Postgresql 存储过程【英文标题】:Creating an array of bytea in Java to pass to a Postgresql stored procedure 【发布时间】:2013-02-16 19:41:33 【问题描述】:

我需要将一个bytea数组传递给一个存储过程(声明的类型if bytea[])。

数据 get 已传递给我的存储过程,但是,我无法从 bytea[] 中获取单个 bytea。 array_lower 和 array_upper 函数报告一维,但 tumb_data[1] 总是返回 NULL。

如果我从存储的过程中打印整个 bytea[] 对象,我会得到以“-1,-40,-1,-32,0,16,74,70,73,70, 0,1,1”,所以我知道数据正在进入程序。

这是一些显示问题的示例代码:

Class.forName("org.postgresql.Driver");
String url = "jdbc:postgresql://localhost/test";
Connection c = DriverManager.getConnection(url,"andres","xxx");
List<byte[]> thumbData=new ArrayList<byte[]>();
thumbData.add("Test #1".getBytes());
thumbData.add("Test #1".getBytes());
Object[] thumbs=thumbData.toArray();
Array thumbArray=c.createArrayOf("bytea", thumbs);
PreparedStatement stmt=c.prepareStatement("SELECT test_funct(?)");
stmt.setArray(1,thumbArray);
stmt.execute();

这是存储过程:

CREATE OR REPLACE FUNCTION test_funct(a_bytes bytea[])
  RETURNS boolean AS
$BODY$DECLARE
    v_bytes bytea;
BEGIN
FOR i IN array_lower(a_bytes,1) .. array_upper(a_bytes,1) LOOP 
        v_bytes:= a_bytes[i];
        IF (v_bytes IS NULL) THEN
            RAISE EXCEPTION 'error';
        END IF; 
    END LOOP;

    RETURN true;
END$BODY$
  LANGUAGE plpgsql VOLATILE
  COST 100;

最后,这是我运行测试程序时的日志输出:

2013-02-17 21:03:52 EST LOG:  execute <unnamed>: SET extra_float_digits = 3
2013-02-17 21:03:52 EST LOG:  execute <unnamed>: SELECT oid FROM pg_catalog.pg_type WHERE typname = $1
2013-02-17 21:03:52 EST DETAIL:  parameters: $1 = '_bytea'
2013-02-17 21:03:52 EST LOG:  execute <unnamed>: SELECT e.typdelim FROM pg_catalog.pg_type t, pg_catalog.pg_type e WHERE t.oid = $1 and t.typelem = e.oid
2013-02-17 21:03:52 EST DETAIL:  parameters: $1 = '1001'
2013-02-17 21:03:52 EST LOG:  execute <unnamed>: SELECT test_funct($1)
2013-02-17 21:03:52 EST DETAIL:  parameters: $1 = '"\\x3834","\\x313031","\\x313135","\\x313136","\\x3332","\\x3335","\\x3439","\\x3834","\\x313031","\\x313135","\\x313136","\\x3332","\\x3335","\\x3439"'
2013-02-17 21:03:52 EST ERROR:  error
2013-02-17 21:03:52 EST STATEMENT:  SELECT test_funct($1)
2013-02-17 21:03:52 EST LOG:  unexpected EOF on client connection

知道如何将它传递给我的存储过程吗?

【问题讨论】:

你能展示你的存储过程吗? PostgreSQL 版本?存储过程语言?过程源? SELECTing 数据的输出? 【参考方案1】:

我怀疑你的数组有两个维度;不是bytea 的一维(线性)数组,而是bytea 的二维数组。索引这样一个数组的第一个维度将产生一个空结果。注意,PostgreSQL 任意维度的数组还是有基本的数组数据类型,没有bytea[][] 等。使用array_ndims(anyarray) 获取数组维度。

观察一维:

WITH t1(ba) AS (VALUES(ARRAY[ '\x0a', '\x0c', '\x0e' ] :: bytea[]))
SELECT ba, ba[1], ba[1][1] FROM t1;
            ba             |  ba  | ba 
---------------------------+------+----
 "\\x0a","\\x0c","\\x0e" | \x0a | 
(1 row)

vs 二维:

WITH t1(ba) AS (VALUES(ARRAY[[ '\x0a', '\x0c', '\x0e' ]] :: bytea[]))
SELECT ba, ba[1], ba[1][1] FROM t1;

             ba              | ba |  ba  
-----------------------------+----+------
 "\\x0a","\\x0c","\\x0e" |    | \x0a
(1 row)

由于您没有显示完整的价值或您的 SQL,因此很难说更多。

如果您怀疑 JDBC 驱动程序有问题,如果您可以提供一个自包含的可编译测试用例来证明该问题(包括用于设置测试数据库的 SQL 脚本),将会有所帮助。

请显示实际运行的 SQL,包括传递的参数。您可以从启用 log_statement 的 PostgreSQL 日志文件中获取此信息。

【讨论】:

Craig,是的,实际上是作为二维数组发送的。你知道如何将它作为一维字节数组发送吗?使用数据类型“text”而不是“bytea”运行完全相同的代码会产生一个一维数组。

以上是关于在 Java 中创建一个 bytea 数组以传递给 Postgresql 存储过程的主要内容,如果未能解决你的问题,请参考以下文章

Hibernate LocalDateTime:Postgresql 模式生成在外部 Tomcat 中创建类型为“bytea”的列

java中创建一个客户类数组customer[] 怎么给数组中的变量赋值?

怎样在MATLAB中创建空的N维数组?

在python中创建没有作为参数传递的aubarrays的子数组

在 bash 3 中创建关联数组

在 JAVA 中创建给出长度和值范围的随机 Int 数组