如何配置 JOOQ 传递十六进制字符串而不是八进制以在 PostgreSQL 中插入 bytea 列?

问题描述 投票:0回答:1

我们正在使用 JOOQ 将记录插入到具有 bytea 列的 postgresql 表中。

我们发送的字节数组约为 150Mb,我们从 Postgresql 服务器收到错误:

错误:无效的内存分配请求大小 1073741824。

深入研究代码并生成查询 JOOQ 后,我们注意到 byteArray 已转换为八进制

(org.jooq.util.postgres.PostgresUtils#toPGString(byte[]))
查询最终看起来像这样:

INSERT INTO test_table (my_data) VALUES (E'\\042\\145\\171...\\042'::bytea);

使用较小的字节数组进行测试发现,插入数据后,其大小确实是字节数组的大小,而不是八进制字符串的大小(八进制字符串更长)。

问题似乎是八进制字符串太长,以至于 postgresql 服务器在尝试将其保存到列之前无法将其转换为 bytea。

有没有办法配置 JOOQ 将

hex
字符串作为值而不是
octal
传递?

我们正在使用 JOOQ 版本

3.16.4
和 postgresql
13.9

澄清编辑:

JOOQ 配置为默认

DefaultConfiguration
。没有进行重大更改。

上面的sql取自抛出的异常:

org.jooq.impl.Tools#translate(java.lang.String, java.lang.RuntimeException)

它打印的 sql 看起来像这样:

org.jooq.exception.DataAccessException: SQL [insert into "public"."table_name" ("id", "name", "version", "description", "archived", "other_id", "jws_data") values (829720463911690240, 'v-0', 'rb-0-6HW7', null, 0, 829720463899107328, E'\\042\\145\\171\\112\\162\\141\\127\\....\135\\175'::bytea) returning "public"."table_name"."id"]; Unspecified RuntimeException

我们没有生成 SQL 插入,而是使用

org.jooq.impl.DAOImpl#insert(P)
并传递 JOOQ 生成的 Record 对象,该对象将 byteArray 作为成员之一 (
jws_data
)。该名称也对应于表中的列名称。

注意:我对 SQL 进行了一些更改以隐藏确切的列名称,因此请忽略名称以及与其他 SQL 的不匹配。

堆栈跟踪:

    toPGString:631, PostgresUtils (org.jooq.util.postgres)
    sqlInline0:2044, DefaultBinding$DefaultBytesBinding (org.jooq.impl)
    sqlInline0:1941, DefaultBinding$DefaultBytesBinding (org.jooq.impl)
    sql:937, DefaultBinding$AbstractBinding (org.jooq.impl)
    sql:929, DefaultBinding$AbstractBinding (org.jooq.impl)
    accept:186, Val (org.jooq.impl)
    visit0:720, DefaultRenderContext (org.jooq.impl)
    visit:295, AbstractContext (org.jooq.impl)
    toSQL92Values:326, FieldMapsForInsert (org.jooq.impl)
    toSQL92Values:278, FieldMapsForInsert (org.jooq.impl)
    accept:137, FieldMapsForInsert (org.jooq.impl)
    visit0:720, DefaultRenderContext (org.jooq.impl)
    visit:295, AbstractContext (org.jooq.impl)
    toSQLInsert:739, InsertQueryImpl (org.jooq.impl)
    accept0:624, InsertQueryImpl (org.jooq.impl)
    accept:642, AbstractDMLQuery (org.jooq.impl)
    visit0:720, DefaultRenderContext (org.jooq.impl)
    visit:295, AbstractContext (org.jooq.impl)
    getSQL0:484, AbstractQuery (org.jooq.impl)
    execute:287, AbstractQuery (org.jooq.impl)
    storeInsert0:191, TableRecordImpl (org.jooq.impl)
    lambda$storeInsert$0:157, TableRecordImpl (org.jooq.impl)
    apply:-1, TableRecordImpl$$Lambda$2120/0x0000000801a5bef8 (org.jooq.impl)
    operate:143, RecordDelegate (org.jooq.impl)
    storeInsert:156, TableRecordImpl (org.jooq.impl)
    insert:144, TableRecordImpl (org.jooq.impl)
    insert:139, TableRecordImpl (org.jooq.impl)
    insert:180, DAOImpl (org.jooq.impl)
    insert:156, DAOImpl (org.jooq.impl)
    save:80, RDBDao (org.jfrog.bintray.distribution.rdb)

可以通过调用来重现相同的行为:

dslContext.insertInto(TEST_TABLE)
          .set(MY_DATA, jws_data_byte_array)
          .execute();

或者

dslContext.execute("insert into test_table (my_data) values (?)", jws_data_byte_array);

同样

toPGString:631, PostgresUtils (org.jooq.util.postgres)
被触发。

java postgresql jooq
1个回答
0
投票

正如@Lukas Eder 提到的, 我们发现一个地方statementType被改为了

STATIC_STATEMENT
而不是默认的
PREPARED_STATEMENT

删除此配置后,JOOQ 停止创建长八进制字符串,并且插入工作完美。

© www.soinside.com 2019 - 2024. All rights reserved.