3

When using PreparedStatements in a regular Java Try-Catch block, I can change the PreparedStatement to run different queries whenever I need, like so:

String sqlStatement = "update someTable set someValue = true";
try{
    PreparedStatement pstmt = con.prepareStatement(sqlStatement);
    pstmt.executeUpdate();

    /* Here I change the query */
    String anotherSqlStatement = "update aDifferentTable set something = false";
    pstmt = con.prepareStatement(anotherSqlStatement);
    pstmt.executeUpdate();
}
catch(Exception ex){
    ...
}

What is the right way to do this using Java's Try-with-Resources? This is what I've tried, but "The resource pstmt of a try-with-resources statement cannot be assigned".

try(Connection con = DriverManager.getConnection(someConnection, user, password);
    PreparedStatement pstmt = con.prepareStatement(sqlStatement)){
    ResultSet rs = pstmt.executeQuery();
    ....

    /* Here I attempt to change the query, but it breaks */
    String anotherSqlStatement = "select something from someTable";
    pstmt = con.prepareStatement(anotherSqlStatement);
}
catch(Exception ex){
    ...
}

I don't want to declare the variable again, I understand that would defeat the purpose of Try-with-Resources, I just want to assign it to something else. What is the correct way to do that?

jabe
  • 784
  • 2
  • 15
  • 33

1 Answers1

8

Consider what would happen if Java let you do this. If you reassign what pstmt references, then after the first PreparedStatement executes then pstmt will refer to the second PreparedStatement. The close method only gets called on what pstmt refers to at the point that the block is finished executing, so close never gets called on the first PreparedStatement.

Instead make nested try-with-resources blocks:

try (Connection con = DriverManager.getConnection(someConnection, user, password)) {
    try (PreparedStatement pstmt = con.prepareStatement(sqlStatement)) {
        pstmt.executeUpdate();
    }

    try (PreparedStatement pstmt = con.prepareStatement(anotherSqlStatement)) {
        pstmt.executeUpdate();            
    }
}

This way there are two pstmt local variables in different scopes. The first PreparedStatement gets closed before the second one begins.

Nathan Hughes
  • 94,330
  • 19
  • 181
  • 276