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
相关产品推荐
相关产品推荐

