如何使用JDBC进行"for update"选择操作?

4
我想使用JDBC创建一个包含for update的选择语句,但不确定如何操作。
如果您不熟悉for update,可以在此处了解更多信息:https://www.postgresql.org/docs/9.0/static/sql-select.html#SQL-FOR-UPDATE-SHARE 例如,我有以下选择语句:
我的选择语句:
select email from email_accounts where already_linked = false order by random() limit 1

我的更新语句

UPDATE email_accounts set already_linked = true, account_link_timestamp = now() where email = ?

如何在使用 for update 的情况下,在 Java 中使用 JDBC 完成此操作?

1个回答

13

你首先需要在你的选择语句(以及其他你想要更新的列)上添加 for update ,然后再更新它们。另外,如评论中所述,请确保您的 getConnection 返回一个没有自动提交的 Connection 。你还需要设置滚动和 CONCUR_UPDATABLE Statement 类型。类似于这样:

String[] colNames = { "email", "already_linked", "account_link_timestamp" };
String query = "select " + Stream.of(colNames).collect(Collectors.joining(", "))
        + "from email_accounts where already_linked = false for update";
try (Connection conn = getConnection(); // Make sure conn.setAutoCommit(false);
        Statement stmt = conn.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, 
                ResultSet.CONCUR_UPDATABLE);
        ResultSet rs = stmt.executeQuery(query)) {
    while (rs.next()) {
        // Get the current values, if you need them.
        String email = rs.getString(colNames[0]);
        boolean linked = rs.getBoolean(colNames[1]);
        Timestamp time = rs.getTimestamp(colNames[2]);
        // ...
        rs.updateBoolean(colNames[1], true);
        rs.updateTimestamp(colNames[2], //
                new Timestamp(System.currentTimeMillis()));
        rs.updateRow();
    }
} catch (SQLException e) {
    e.printStackTrace();
}

1
conn.setAutoCommit = false 对于 for update 锁是否有效是必要的,还是无关紧要的? - Gord Thompson
1
此外,createStatement 不是需要使用 ResultSet.CONCUR_UPDATABLE 进行调用,以便 updateRow 能够正常工作吗? - Gord Thompson
@Arya - 那应该没问题,但你也需要记得conn.commit()提交更改。 - Gord Thompson
4
你可能需要在 SELECT 语句中包含主键列,以便通过 JDBC 更新结果集,即将其添加到 colNames 中。 - Mick Mnemonic
我无法将此用于所有状态为=0的记录组,我们始终需要在select for update语句中具有主键,否则ResultSet上的更新会抛出java.sql.SQLException:ORA-01446:无法从DISTINCT、GROUP BY等视图中选择ROWID或样本。我希望在select查询中使用rs.updateXXX(),以锁定多个记录(例如100条)。看不到其他解决方法。 - Prosenjit
显示剩余10条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接