tags:

views:

134

answers:

2

I want to update every row on a specific column in a mySql database. Currently I am using a java.sql.PreparedStatement for each row and iterating in a for loop. I was wondering if there were any other alternatives in terms of Java programming to make this less time and resource consuming (something like executing the prepared statements in a batch). The updates are made from java code because that is where I get the values from. I am also not interested in making stored procedures on the server as I do not have the rights for that.

+2  A: 

Here is a link to an example that uses Java's prepared statement to execute a batch update. I also included the sample from the site for quick reference.

http://www.exampledepot.com/egs/java.sql/BatchUpdate.html

try {
    // Disable auto-commit
    connection.setAutoCommit(false);

    // Create a prepared statement
    String sql = "INSERT INTO my_table VALUES(?)";
    PreparedStatement pstmt = connection.prepareStatement(sql);

    // Insert 10 rows of data
    for (int i=0; i<10; i++) {
     pstmt.setString(1, ""+i);
     pstmt.addBatch();
    }

    // Execute the batch
    int [] updateCounts = pstmt.executeBatch();

    // All statements were successfully executed.
    // updateCounts contains one element for each batched statement.
    // updateCounts[i] contains the number of rows affected by that statement.
    processUpdateCounts(updateCounts);

    // Since there were no errors, commit
    connection.commit();
} catch (BatchUpdateException e) {
    // Not all of the statements were successfully executed
    int[] updateCounts = e.getUpdateCounts();

    // Some databases will continue to execute after one fails.
    // If so, updateCounts.length will equal the number of batched statements.
    // If not, updateCounts.length will equal the number of successfully executed statements
    processUpdateCounts(updateCounts);

    // Either commit the successfully executed statements or rollback the entire batch
    connection.rollback();
} catch (SQLException e) {
}

public static void processUpdateCounts(int[] updateCounts) {
    for (int i=0; i<updateCounts.length; i++) {
     if (updateCounts[i] >= 0) {
      // Successfully executed; the number represents number of affected rows
     } else if (updateCounts[i] == Statement.SUCCESS_NO_INFO) {
      // Successfully executed; number of affected rows not available
     } else if (updateCounts[i] == Statement.EXECUTE_FAILED) {
      // Failed to execute
     }
    }
}
hoffmandirt
Side note: If you're using the MyIsam engine, setAutoCommit has no effect. Everything is always auto-commit.
Jay
Thanks! this was exactly what I was looking for. Batching the update statements made a big difference. The time on my test went from like 50 seconds down to around 10.
Vlad T.
A: 

If you're using MySQL, I believe the short answer to your question is "No". There's nothing you can do that will be any faster.

Indeed, even the prepared statement gains you nothing. Perhaps this is changed with newer versions, but last I checked (several years ago), MySQL just turns prepared statements into regular statements anyway. Nothing is cached.

Jay
PreparedStatements (used correctly) still buy you safety from SQL injection attacks at the very least.
Joachim Sauer
Joachim: Absolutely true. Beyond that I think it's largely a matter of style.
Jay