My Java JDBC call for a Batch-Update is structured as
conn.setAutoCommit(false);
for (int i = 0; i < items.size(); i++) {
//...
ps.addBatch();
}
ps.executeBatch();
// Suppose an exception happens right before a Commit
if (someCondition)
throw new Exception("test");
conn.commit(); // Commit at the very end
My understanding is, when that Exception happens, I never reached a commit
. So my data shouldn't be persisted, right? As long as the commit
is at the very end, and setAutoCommit(false);
is specified, any exceptions don't require a rollback?
But I see that the data does get persisted. My question is why? And do I need a connection.rollback();
? (This is with a Postgres DB)
Please take a look at the transaction isolation levels of PostgreSQL:
https://www.postgresql.org/docs/9.5/transaction-iso.html
The default is READ COMMITTED which is good for you.
Reading back 'uncommited' changes depends on the JDBC connection you're using. Every connection will have a different 'view' on the data depending on the transaction isolation level.
Best practice when setting
conn.setAutoCommit(false);
is to have a commit at success and a rollback in a catch clause:
conn.setAutoCommit(false);
try {
...
ps.executeBatch();
conn.commit();
} catch (Exception e) {
conn.rollback();
}
Calling neither commit nor rollback will keep the connection open, putting load on the database for maintaining uncommitted changes. The JVM will then some time close the connection and the database will roll back all data.
JEE containers roll back transaction automatically when uncaught exceptions happen.