JDBCトランザクションを使用すると、トランザクションをデータベースにコミットする方法とタイミングを制御できます。

…​.//transaction block start

単純なJDBCトランザクションでは、トランザクションブロック内のSQLステートメントのいずれかが失敗した場合、トランザクションブロック内のSQLステートメントがすべて正常に実行されたことを確認し、トランザクションブロック内のすべてを中断してロールバックします。

JDBCトランザクションの仕組みを理解するには、以下の2つの例を参照してください。

===  1. JDBCトランザクションなし

デフォルトでは、 `executeUpdate()`が呼び出されるとデータはデータベースにコミットされます。

String insertTableSQL = “INSERT INTO DBUSER”
+ “(USER

ID, USERNAME, CREATED

BY, CREATED__DATE) VALUES”
+ “(?,?,?,?)”;

String updateTableSQL = “UPDATE DBUSER SET USERNAME =? ”
+ “WHERE USER__ID = ?”;

preparedStatementInsert = dbConnection.prepareStatement(insertTableSQL);
preparedStatementInsert.setInt(1, 999);
preparedStatementInsert.setString(2, “mkyong101”);
preparedStatementInsert.setString(3, “system”);
preparedStatementInsert.setTimestamp(4, getCurrentTimeStamp());
preparedStatementInsert.executeUpdate();//data COMMITTED into database.

preparedStatementUpdate = dbConnection.prepareStatement(updateTableSQL);
preparedStatementUpdate.setString(1, “A very very long string caused DATABASE ERROR”);
preparedStatementUpdate.setInt(2, 999);

preparedStatementUpdate.executeUpdate();//Error, value too big, ignore this update statement,
//but user__id=999 is inserted

このコードを実行すると、USER__ID = '999'が挿入されますが、ユーザー名は更新されません。

===  2. JDBCトランザクション

これをトランザクションに入れるには、

.  `dbConnection.setAutoCommit(false);`トランザクションブロックを開始します.

. トランザクションブロックを終了するには `dbConnection.commit();`を実行します.

コードスニペットを参照してください:

dbConnection.setAutoCommit(false);//transaction block start

String insertTableSQL = “INSERT INTO DBUSER”
+ “(USER

ID, USERNAME, CREATED

BY, CREATED__DATE) VALUES”
+ “(?,?,?,?)”;

String updateTableSQL = “UPDATE DBUSER SET USERNAME =? ”
+ “WHERE USER__ID = ?”;

preparedStatementInsert = dbConnection.prepareStatement(insertTableSQL);
preparedStatementInsert.setInt(1, 999);
preparedStatementInsert.setString(2, “mkyong101”);
preparedStatementInsert.setString(3, “system”);
preparedStatementInsert.setTimestamp(4, getCurrentTimeStamp());
preparedStatementInsert.executeUpdate();//data IS NOT commit yet

preparedStatementUpdate = dbConnection.prepareStatement(updateTableSQL);
preparedStatementUpdate.setString(1, “A very very long string caused DATABASE ERROR”);
preparedStatementUpdate.setInt(2, 999);
preparedStatementUpdate.executeUpdate();//Error, rollback, including the first insert statement.

dbConnection.commit();//transaction block end

このコードが実行されると、update文はヒットエラーとなり、insert文とupdate文の両方をロールバックします。

=== 完全なJDBCトランザクションの例

完全なJDBCトランザクションの例を参照してください。

package com.mkyong.jdbc;

import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.SQLException;

public class JDBCTransactionExample {

private static final String DB__DRIVER = "oracle.jdbc.driver.OracleDriver";
private static final String DB__CONNECTION = "jdbc:oracle:thin:@localhost:1521:MKYONG";
private static final String DB__USER = "user";
private static final String DB__PASSWORD = "password";

public static void main(String[]argv) throws SQLException {

Connection dbConnection = null;
PreparedStatement preparedStatementInsert = null;
PreparedStatement preparedStatementUpdate = null;

String insertTableSQL = "INSERT INTO DBUSER"
        + "(USER__ID, USERNAME, CREATED__BY, CREATED__DATE) VALUES"
        + "(?,?,?,?)";

String updateTableSQL = "UPDATE DBUSER SET USERNAME =? "
        + "WHERE USER__ID = ?";

try {
    dbConnection = getDBConnection();

dbConnection.setAutoCommit(false);

preparedStatementInsert = dbConnection.prepareStatement(insertTableSQL);
preparedStatementInsert.setInt(1, 999);
preparedStatementInsert.setString(2, "mkyong101");
preparedStatementInsert.setString(3, "system");
preparedStatementInsert.setTimestamp(4, getCurrentTimeStamp());
preparedStatementInsert.executeUpdate();

 preparedStatementUpdate = dbConnection.prepareStatement(updateTableSQL);
//preparedStatementUpdate.setString(1,
//"A very very long string caused db error");
 preparedStatementUpdate.setString(1, "new string");
 preparedStatementUpdate.setInt(2, 999);
 preparedStatementUpdate.executeUpdate();

dbConnection.commit();

System.out.println("Done!");

} catch (SQLException e) {

System.out.println(e.getMessage());
dbConnection.rollback();

} finally {

if (preparedStatementInsert != null) {
    preparedStatementInsert.close();
}

if (preparedStatementUpdate != null) {
    preparedStatementUpdate.close();
}

if (dbConnection != null) {
    dbConnection.close();
}

}

}

private static Connection getDBConnection() {

Connection dbConnection = null;

try {

Class.forName(DB__DRIVER);

} catch (ClassNotFoundException e) {

System.out.println(e.getMessage());

}

try {

dbConnection = DriverManager.getConnection(DB__CONNECTION, DB__USER,
        DB__PASSWORD);
return dbConnection;

} catch (SQLException e) {

System.out.println(e.getMessage());

}

return dbConnection;

}

private static java.sql.Timestamp getCurrentTimeStamp() {

java.util.Date today = new java.util.Date();
return new java.sql.Timestamp(today.getTime());

}

}

link://tag/jdbc/[jdbc]link://タグ/トランザクション/[トランザクション]