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

JDBI调用PostgreSQL函数获取返回结果时遇异常问题

问题分析

哦,我知道你卡在哪了——你用错JDBI的API啦!createCall这个方法是专门用来调用存储过程或者用SQL的CALL语法执行函数的,但你这里写的是普通的SELECT查询,用它自然会抛出异常。

正确的实现方式

下面给你几种可行的写法,选适合你的就行:

方式一:用createQuery执行SELECT语句

这是最直接的方式,你的SQL就是普通查询,完全没必要用createCall:

public String test() {
    // 用try-with-resources自动关闭Handle,不用手动写finally
    try (Handle h = dbi.open()) {
        return h.createQuery("SELECT foo('hi') as result")
                .mapTo(String.class) // 直接把结果映射到String类型
                .one(); // 因为只返回一行结果,用one()获取
    }
}

方式二:直接调用PostgreSQL函数(更贴合JDBI风格)

如果想更优雅地调用函数,可以用createCall配合PostgreSQL的函数调用语法(PostgreSQL 11+支持这种CALL方式):

public String test() {
    try (Handle h = dbi.open()) {
        OutParameters ret = h.createCall("{? = CALL foo(?)}")
                .registerOutParameter(1, Types.VARCHAR) // 注册返回值的参数类型
                .bind(2, "hi") // 绑定输入参数
                .invoke();
        return ret.getString(1);
    }
}

方式三:用JDBI的简化查询API

JDBI还有更简洁的写法,一行就能搞定:

public String test() {
    try (Handle h = dbi.open()) {
        return h.select("SELECT foo(?) as result", "hi")
                .mapTo(String.class)
                .one();
    }
}
额外小提示
  • 一定要用try-with-resources管理Handle,它会自动帮你关闭资源,避免手动写finally可能出现的遗漏,代码也更清爽。
  • 如果你经常调用这个函数,还可以用JDBI的@SqlFunction注解定义DAO接口,更符合规范:
public interface FooDao {
    @SqlFunction("foo")
    String callFoo(@Bind("bar") String bar);
}

// 使用的时候
FooDao dao = dbi.onDemand(FooDao.class);
String result = dao.callFoo("hi");

内容的提问来源于stack exchange,提问作者Math is Hard

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:50:26