セーブポイントの使用
セーブポイントは、トランザクションを部分的にロールバックするメカニズムです。 SQL Server 内に、SAVE TRANSACTION savepoint_name ステートメントを使用してセーブポイントを作成できます。 その後 ROLLBACK TRANSACTION savepoint_name ステートメントを実行すると、トランザクションの最初にロールバックするのではなく、セーブポイントにロールバックされます。
セーブポイントは、エラーが発生する可能性が小さい状況で役立ちます。 エラーの頻度が低い場合には、セーブポイントを使用してトランザクションの一部をロールバックする方法は、更新が有効であるかどうかを更新を行う前にトランザクションごとにテストするよりも効率的です。 更新とロールバックは負荷の大きい処理です。そのため、セーブポイントが効果を発揮するのは、エラーの発生確率が低く、なおかつ更新の有効性を事前にチェックするコストの方が高い場合に限られます。
Microsoft JDBC Driver for SQL Server では、SQLServerConnection クラスの setSavepoint メソッドを介したセーブポイントの使用がサポートされています。 setSavepoint メソッドを使用することで、名前付きセーブポイントまたは名前を割り当てられていないセーブポイントを、現在のトランザクションに作成できます。またこのメソッドによって SQLServerSavepoint オブジェクトが返されます。 セーブポイントは 1 つのトランザクションに複数作成できます。 特定のセーブポイントまでトランザクションをロールバックするには、SQLServerSavepoint オブジェクトを rollback (java.sql.Savepoint) メソッドに渡します。
次の例では、try
ブロック内の 2 つの個別のステートメントで構成されるローカル トランザクションの実行時にセーブポイントが使用されます。 AdventureWorks2022 サンプル データベースの Production.ScrapReason テーブルに対してステートメントが実行され、セーブポイントを使って 2 番目のステートメントがロールバックされます。 この結果、最初のステートメントのみがデータベースにコミットされます。
public static void executeTransaction(Connection con) {
try(Statement stmt = con.createStatement();) {
con.setAutoCommit(false);
stmt.executeUpdate("INSERT INTO Production.ScrapReason(Name) VALUES('Correct width')");
Savepoint save = con.setSavepoint();
stmt.executeUpdate("INSERT INTO Production.ScrapReason(Name) VALUES('Wrong width')");
con.rollback(save);
con.commit();
System.out.println("Transaction succeeded.");
}
catch (SQLException ex) {
ex.printStackTrace();
try {
System.out.println("Transaction failed.");
con.rollback();
}
catch (SQLException se) {
se.printStackTrace();
}
}
}