Search code examples
sqljdbcderby

How do I update just retrieved records without issuing an additional query?


I have the following piece of code:

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
}   

Considering that I have already searched the database, I'm wondering if there is a way I can get the row number/position,and use it to update the UUID column, hence preventing another DB search.


Solution

  • It's not clear what you are trying to do here, and it doesn't really seem you understand what goes on. For example, when using a prepared statement, one doesn't feed it with two concatenated strings, but instead does:

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

    Then, if you really want to avoid the double search, you can simply assume an optimistic point of view:

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

    Ensure that the email is unique, by the way. Also, maybe you already do it, but don't save plaintext passwords in the db. Use cryptographic hashes instead, and salt them.

    Since you specify that your backend is Apache Derby, maybe this guide can help you solve your problem (it's 100% Java but not truly portable because of different backends may not implement all of the required features). Basically, you pass two flags when preparing the statement:

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

    and then you have a ResultSet backed by an updateable cursor, so you can call:

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

    I think this may avoid the additional search, however I didn't test it and cannot say if there's a real performance gain. Sounds like premature optimization, though.