Im using Statement
s batchs to query my data base.
Iv'e done some research now and i want to rewrite my application to use preparedStatement
instead but i'm having hard time to figure out how to add queries to a preparedStatement
batch.
This is what i'm doing now:
private void addToBatch(String sql) throws SQLException{
sttmnt.addBatch(sql);
batchSize++;
if (batchSize == elementsPerExecute){
executeBatches();
}
}
where sttmnt
is a class member of type Statement
.
What i want to do is to use the preparedStatement
's setString(int, String)
method to set some dynamic data and then add it to the batch.
Unfortunately, i don't fully understand how it works, and how i can use setString(int, String)
to a specific sql in the batch OR create a new preparedStatemnt
for every sql i have and then join them all to one batch.
is it possible to do that? or am i really missing something in my understanding of preparedStatement
?
Read the section 6.1.2 of this document for examples. Basically you use the same statement object and invoke the batch method after all the placeholders are set. Another IBM DB2 example which should work for any JDBC implementation. From the second site:
try {
connection con.setAutoCommit(false);
PreparedStatement prepStmt = con.prepareStatement(
"UPDATE DEPT SET MGRNO=? WHERE DEPTNO=?");
prepStmt.setString(1,mgrnum1);
prepStmt.setString(2,deptnum1);
prepStmt.addBatch();
prepStmt.setString(1,mgrnum2);
prepStmt.setString(2,deptnum2);
prepStmt.addBatch();
int [] numUpdates=prepStmt.executeBatch();
for (int i=0; i < numUpdates.length; i++) {
if (numUpdates[i] == -2)
System.out.println("Execution " + i +
": unknown number of rows updated");
else
System.out.println("Execution " + i +
"successful: " + numUpdates[i] + " rows updated");
}
con.commit();
} catch(BatchUpdateException b) {
// process BatchUpdateException
}
With PreparedStatement
's you have wild cards in a way, for example
Sring query = "INSERT INTO users (id, user_name, password) VALUES(?,?,?)";
PreparedStatement statement = connection.preparedStatement(query);
for(User user: userList){
statement.setString(1, user.getId()); //1 is the first ? (1 based counting)
statement.setString(2, user.getUserName());
statement.setString(3, user.getPassword());
statement.addBatch();
}
This will create 1 PreparedStatement
with that query shown above.You can loop through list when you want to insert or whatever you intentions are. When you want to execute you,
statement.executeBatch();
statement.clearBatch(); //If you want to add more,
//(so you don't do the same thing twice)
I'm adding an extra answer here specifically for MySQL.
I found that the time to do a batch of inserts was similar to the length of time to do individual inserts, even with the single transaction around the batch.
I added the parameter rewriteBatchedStatements=true
to my jdbc url, and saw a dramatic improvement - in my case, a batch of 200 inserts went from 125 msec. without the parameter to about 10 to 15 msec. with the parameter.
See MySQL and JDBC with rewriteBatchedStatements=true