I'm trying to get JdbcTemplate.batchUpdate() to work the way I would expect -- namely, I'd like it to hold off the commit until the whole batch has been processed. Perhaps one of you can explain the behavior I'm seeing.
First let me show some regular JDBC code that does what I'd like:
static void do_jdbc(){
String url = "jdbc:mysql://localhost/mydb";
Connection con;
Statement stmt = null;
try {
Class.forName("com.mysql.jdbc.Driver");
} catch (java.lang.ClassNotFoundException e) {
System.err.print("ClassNotFoundException: ");
System.err.println(e.getMessage());
}
try {
con = DriverManager.getConnection(url, "root", "");
stmt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIV E, ResultSet.CONCUR_UPDATABLE);
con.setAutoCommit(false);
for (int i = 0; i < 2; i++) {
StringBuffer buf = new StringBuffer("insert into table1(field1, field2) value").append("('dummy").append(i).append("', ").append(i).append(")");
stmt.addBatch(buf.toString());
}
int[] updateCounts = stmt.executeBatch();
con.commit();
stmt.close();
} catch (Exception e) {
e.printStackTrace();
}
}
This works fine and generates the following output in the MySql log file:
7 Query SET autocommit=1
7 Query SET autocommit=0
7 Query insert into table1(field1, field2) value('dummy0', 0)
7 Query insert into table1(field1, field2) value('dummy1', 1)
7 Query commit
When I try to do essentially the same thing using JdbcTemplate, tho', I get some unexpected behavior. Here's the code:
static void do_spring(){
BasicDataSource ds = new BasicDataSource();
ds.setDriverClassName("com.mysql.jdbc.Driver");
ds.setUsername("root");
ds.setPassword("");
ds.setUrl("jdbc:mysql://localhost/mydb");
ds.setDefaultAutoCommit(false);
JdbcTemplate t = new JdbcTemplate();
t.setDataSource(ds);
BatchPreparedStatementSetter setter = new BatchPreparedStatementSetter() {
public void setValues(PreparedStatement preparedStatement, int i) throws SQLException {
preparedStatement.setString(1, "dummy" + i);
preparedStatement.setInt(2, i);
}
public int getBatchSize() {
return 2;
}
};
try {
int[] rowCounts = t.batchUpdate("insert into table1(field1, field2) value(?,?)", setter);
} catch (Exception e) {
e.printStackTrace();
}
}
This generates the following in the log file:
2 Query SET autocommit=1
2 Query SET autocommit=0
2 Prepare [1]
2 Execute [1] insert into table1(field1, field2) value('dummy0',0)
2 Execute [1] insert into table1(field1, field2) value('dummy1',1)
2 Query SHOW WARNINGS
2 Query rollback
2 Query SET autocommit=1
If I leave out the
ds.setDefaultAutoCommit(false);
then 'autocommit' stays at '1' and the inserts work (no 'rollback'), but each one is committed individually, which is about two-orders-of-magnitude slower for any significant amount of data.
Can someone please tell me how to fix it with the Spring classes (programmatically, not in bean-definition XML files) so that it successfully updates the database, but all-at-once?
Thanks in advance.