You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Java 1.8+Jooq 3.10.3调用Postgres 10.1表参数函数报错求助

问题分析与解决方案

你遇到的这个报错,核心原因是PostgreSQL的表行类型(testtab类型)和jOOQ生成的TesttabRecord Java对象无法直接自动映射。jOOQ默认不会把TesttabRecord实例转换成PostgreSQL能识别的行类型参数,所以抛出了SQLDialectNotSupportedException。

下面是具体的修复方案和注意事项:


方案1:手动构造行类型参数调用函数

你可以用jOOQ的DSL.row()方法构造符合PostgreSQL行类型要求的参数,替代直接传入TesttabRecord对象。两种实现方式如下:

方式A:结合生成的Testfunc类调用

try (Connection conn = DriverManager.getConnection(url, userName, password)) {
    DSLContext cxt = DSL.using(conn, SQLDialect.POSTGRES);
    TesttabRecord r = new TesttabRecord(1, "test");
    
    // 用row()方法构造匹配testtab行类型结构的参数
    Row2<Integer, String> rowParam = DSL.row(r.getId(), r.getTxt());
    
    Testfunc f = new Testfunc();
    f.setVal(rowParam); // 传入Row对象而非TesttabRecord
    f.execute(cxt.configuration());
}

方式B:直接用DSL API调用函数(更灵活)

try (Connection conn = DriverManager.getConnection(url, userName, password)) {
    DSLContext cxt = DSL.using(conn, SQLDialect.POSTGRES);
    TesttabRecord r = new TesttabRecord(1, "test");
    
    Row2<Integer, String> rowParam = DSL.row(r.getId(), r.getTxt());
    // 直接调用PostgreSQL函数
    cxt.execute(DSL.select(DSL.function("testfunc", Void.class, rowParam)));
}

方案2:通过代码生成器优化类型映射

如果想更优雅地使用表类型参数,可以让jOOQ为PostgreSQL的表行类型生成对应的UDT(用户定义类型)类。需要修改jOOQ生成器配置,开启UDT支持:

生成器配置示例(XML)

<generator>
    <database>
        <name>org.jooq.meta.postgres.PostgresDatabase</name>
        <!-- 开启UDT生成,包含PostgreSQL的表行类型 -->
        <includeUDTs>true</includeUDTs>
        <!-- 指定要生成的对象,按需调整 -->
        <includes>testtab|testfunc</includes>
    </database>
</generator>

重新生成代码后,jOOQ会生成Testtab UDT类,此时可以把TesttabRecord转换为UDT对象传入函数:

try (Connection conn = DriverManager.getConnection(url, userName, password)) {
    DSLContext cxt = DSL.using(conn, SQLDialect.POSTGRES);
    TesttabRecord r = new TesttabRecord(1, "test");
    
    // 将Record转换为UDT对象
    Testtab udtParam = Testtab.values(r.getId(), r.getTxt());
    
    Testfunc f = new Testfunc();
    f.setVal(udtParam);
    f.execute(cxt.configuration());
}

额外重要修复:PostgreSQL函数逻辑错误

你的函数内部的插入语句存在问题:insert into testtab select * from val中,val是单个行类型变量,不是表,执行时会报"more than one row returned by a subquery used as an expression"错误。需要修改为以下两种写法之一:

-- 写法1:直接引用行类型的字段
CREATE OR REPLACE FUNCTION public.testfunc(val testtab) RETURNS void 
LANGUAGE 'plpgsql' AS $$
begin 
    insert into testtab(id, txt) values (val.id, val.txt); 
end; 
$$;
-- 写法2:用括号包裹行类型,展开所有字段
CREATE OR REPLACE FUNCTION public.testfunc(val testtab) RETURNS void 
LANGUAGE 'plpgsql' AS $$
begin 
    insert into testtab select (val).*; 
end; 
$$;

内容的提问来源于stack exchange,提问作者codemonkey

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:42:07