I use sqlite
database and java.sql
classes in servlet application to batch-insert some data into database. There are consecutive four inserts of different kinds of data. Each one looks like this:
PreparedStatement statement = conn
.prepareStatement("insert or ignore into nodes(name,jid,available,reachable,responsive) values(?,?,?,?,?);");
for (NodeInfo n : nodes)
{
statement.setString(1, n.name);
statement.setString(2, n.jid);
statement.setBoolean(3, n.available);
statement.setBoolean(4, n.reachable);
statement.setBoolean(5, n.responsive);
statement.addBatch();
}
conn.setAutoCommit(false);
statement.executeBatch();
conn.commit();
conn.setAutoCommit(true);
statement.close();
But sometimes I get the
java.sql.SQLException: database in auto-commit mode
I found in source code of java.sql.Connection
that this exception is thrown when calling commit()
while database is in autocommit mode. But I turn autocommit off before and I can't see any place for some parallel execution related issues as for now application is only turned on once.
Do you have any idea how to debug this issue? Maybe there's some other reason for this error (because I just found that exception about database not found or not well configured can be thrown when inserting null
into non-null field)?.
May be an issue is with order of statements. Your database statement should be :
PreparedStatement statement1 = null;
PreparedStatement statement2 = null;
Connection connection=null;
try {
//1. Obtain connection and set `false` to autoCommit
connection.setAutoCommit(false);
//2. Prepare and execute statements
statement1=connection.prepareStatement(sql1);
statement2=connection.prepareStatement(sql2);
...
//3. Execute the statements
statement1.executeUpdate();
statement2.executeUpdate();
//4. Commit the changes
connection.commit();
}
} catch (SQLException e ) {
if (connection!=null) {
try {
connection.rollback();
} catch(SQLException excep) {}
}
}finally {
if (statement1 != null) {
statement1.close();
}
if (statement2 != null) {
statement2.close();
}
if(connection != null){
connection.setAutoCommit(true);
connection.close();
}
}
You have to prepare your Statement and create the batch after conn.setAutoCommit(false);
.
When running this from a servlet, you have to make sure that the usage of the Connection
is synchronized. Multiple requests could set the Connection
to a different auto commit mode at nearly the same time. If you use one Connection
per request, this will not be an issue. Otherwise, protect the above part with a critical section.
A tip regarding debugging which is applicable for tomcat / eclipse.
1) Enable JDPA debugging for your application server. In tomcat you can do this by adding the following lines to catalina.sh / catalina.bat:
set JPDA_ADDRESS=8000
set JPDA_TRANSPORT=dt_socket
2) Restart the application server
3) Connect with eclipse to your application server. "Debug as" --> "Remote Java Application"
4) Set a break point in above code.
5) Run the servlet.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.