PostgreSQL使用UPDATE with RETURNING时Java无法获取ResultSet问题
问题核心原因
你遇到的问题是JDBC结果处理逻辑不符合规范,以及没有适配PostgreSQL带RETURNING子句的DML语句的执行要求:
- 带
RETURNING的UPDATE语句会返回两个结果:第一个是更新行数计数,第二个才是RETURNING返回的结果集; - 你原代码的结果处理逻辑跳过了更新计数的读取步骤,直接调用
getMoreResults()拿不到后续的结果集。
可行解决方案
- 方案1:直接使用
executeQuery()执行语句
这是最简单的方案,RETURNING子句最终会返回结果集,PostgreSQL JDBC驱动支持直接用executeQuery()执行带返回的DML语句,直接拿到结果集:
PreparedStatement statement = this.prepareStatement( "WITH temp AS (" + " SELECT id" + " FROM mytable " + " LIMIT 5 " ") " + "UPDATE mytable " + "SET updated = NOW() " + "FROM temp " + "WHERE temp.id = mytable.id " + "RETURNING mytable.data" ); // 直接执行并获取返回结果集 ResultSet resultSet = statement.executeQuery(); while (resultSet.next()) { // 处理返回的data字段 String data = resultSet.getString("data"); }
- 方案2:修正
execute()的结果处理顺序
如果必须用execute()方法,需要按照JDBC规范先读取更新计数,再调用getMoreResults()获取后续的结果集:
boolean hasResult = statement.execute(); // 第一个结果是更新计数,先读取,不用处理的话可以忽略返回值 int updateCount = statement.getUpdateCount(); // 再调用getMoreResults才能拿到RETURNING的结果集 hasResult = statement.getMoreResults(); if (hasResult) { ResultSet resultSet = statement.getResultSet(); // 处理结果集 }
- 方案3:创建Statement时指定返回生成键
构造PreparedStatement时传入Statement.RETURN_GENERATED_KEYS参数,RETURNING的结果会被封装到生成键结果集中,可直接通过getGeneratedKeys()获取:
// 构造时添加第二个参数 PreparedStatement statement = this.prepareStatement( "WITH temp AS (" + " SELECT id" + " FROM mytable " + " LIMIT 5 " ") " + "UPDATE mytable " + "SET updated = NOW() " + "FROM temp " + "WHERE temp.id = mytable.id " + "RETURNING mytable.data", Statement.RETURN_GENERATED_KEYS ); // 执行后直接拿生成键结果集 statement.executeUpdate(); ResultSet resultSet = statement.getGeneratedKeys(); while (resultSet.next()) { String data = resultSet.getString("data"); }
内容的提问来源于stack exchange,提问作者Rob
相关产品推荐
相关产品推荐

