如何在不发出其他查询的情况下更新检索到的记录?

时间:2013-04-06 08:35:16

标签: sql jdbc derby

我有以下代码:

String sql = "SELECT * FROM users WHERE email = " + email;
prestat = DBConnection.prepareStatement(sql);
rs = prestat.executeQuery();
boolean isEmpty = !rs.first();
if (isEmpty) {
  // Special marker for nonexistent user
  return "$null";
} else if (password.equals(rs.getString(2))) {
  String uuid = UUID.randomUUID().toString();
  // Here I want to insert the UUID into the database
}   

考虑到我已经搜索了数据库,我想知道是否有办法获取行号/位置,并使用它来更新UUID列,从而阻止了另一个数据库搜索。

2 个答案:

答案 0 :(得分:3)

目前尚不清楚你在这里要做什么,而且你似乎并不了解发生了什么。例如,当使用预准备语句时,不会使用两个连接字符串来提供它,而是使用:

PreparedStatement stmt =
        conn.prepareStatement("SELECT * FROM foo WHERE bar = ?");
stmt.setString(1, "Hello World!");

然后,如果你真的想避免双重搜索,你可以简单地假设一个乐观的观点:

UPDATE users SET uuid = ? WHERE email = ? AND password = ?

顺便说一下,确保电子邮件是唯一的。此外,也许您已经这样做了,但不要在db中保存明文密码。请使用加密哈希,并加盐。

由于您指定后端是Apache Derby,因此this guide可以帮助您解决问题(它是100%Java但不是真正可移植的,因为不同的后端可能无法实现所有必需的功能)。基本上,在准备语句时传递两个标志:

Statement stmt = con.createStatement(
    ResultSet.TYPE_FORWARD_ONLY, 
    ResultSet.CONCUR_UPDATABLE);
ResultSet res = stmt.executeQuery("SELECT * FROM users WHERE email = ?");

然后你有一个ResultSet由可更新的游标支持,所以你可以调用:

res.updateString("uuid", uuid);
res.updateRow();

我认为可以避免额外的搜索,但我没有测试它,也不能说是否有真正的性能提升。听起来像过早的优化。

答案 1 :(得分:1)

你可以简单地替换

prestat = DBConnection.prepareStatement("SELECT * FROM users WHERE email =" + email);

通过

prestat = DBConnection.prepareStatement("Update users set uuid = '" + uuid + "' WHERE email =" + email);

当然是执行。