トランザクション
| 日本語 | 業務処理 |
| 英語 | transaction |
| ふりがな | とらんざくしょん |
| フリガナ | トランザクション |
やり直し可能なSQL。
SQLを「トランザクションモード」で実行した時、その間のINSERT、DELETE、UPDATEといったデータの変更を伴うSQLを「とりあえずの更新」とすることができ、「コミット」で確定、「ロールバック」で取り消すことができる。
たとえば「テーブルAに行1がある場合には必ずテーブルBにも行2がなければならない」といった場合、行1と行2をINSERTする間にエラーが発生した時に「行1のみINSERTされる」ということになってはいけない。トランザクションモードの場合、ロールバックを行うことで「行1へのINSERT」を取り消せるため、行1のINSERTの前に「トランザクション開始」を行い、行2のINSERT後に「コミット」し、エラーが発生した場合には「ロールバック」するようにする。
このように、厳密な業務処理ではトランザクション処理は必須である。
SQLでトランザクションを実行する場合、まずデータベースの設定を確認する必要がある。
通常、データベースの設定はトランザクション処理を行わない「オートコミット」となっており、INSERT、DELETE、UPDATEを行うと即座にコミットされる。
オートコミットモードの場合、トランザクションはBEGINで開始する。BEGIN後のINSERT、DELETE、UPDATEは仮の変更となる。
COMMITでコミット、ROLLBACKでロールバックを行う。
JDBCを使用する場合、これらはConnectionインターフェイスの専用メソッドを使用して行う。
まず、ConnectionインターフェイスのsetAutoCommit()メソッドにfalseを渡すことで、オートコミットをオフにし、トランザクションモードを開始する。
コミットはConnectionインターフェイスのcommit()メソッド、ロールバックはrollback()メソッドで行う。
また、先ほどの例のように「エラー時にはロールバックする」場合には、finallyブロック内でrollback()メソッドを呼んでから、各close()を呼び出すようにする。
トランザクションは厳密な業務処理では必須のため、完全に理解して使いこなせるようにしておくこと。
コミットやロールバックの他にも、FOR UPDATEを使用した排他にも使用したりと、使い道は多い。
SQLを「トランザクションモード」で実行した時、その間のINSERT、DELETE、UPDATEといったデータの変更を伴うSQLを「とりあえずの更新」とすることができ、「コミット」で確定、「ロールバック」で取り消すことができる。
たとえば「テーブルAに行1がある場合には必ずテーブルBにも行2がなければならない」といった場合、行1と行2をINSERTする間にエラーが発生した時に「行1のみINSERTされる」ということになってはいけない。トランザクションモードの場合、ロールバックを行うことで「行1へのINSERT」を取り消せるため、行1のINSERTの前に「トランザクション開始」を行い、行2のINSERT後に「コミット」し、エラーが発生した場合には「ロールバック」するようにする。
このように、厳密な業務処理ではトランザクション処理は必須である。
SQLでトランザクションを実行する場合、まずデータベースの設定を確認する必要がある。
通常、データベースの設定はトランザクション処理を行わない「オートコミット」となっており、INSERT、DELETE、UPDATEを行うと即座にコミットされる。
オートコミットモードの場合、トランザクションはBEGINで開始する。BEGIN後のINSERT、DELETE、UPDATEは仮の変更となる。
COMMITでコミット、ROLLBACKでロールバックを行う。
JDBCを使用する場合、これらはConnectionインターフェイスの専用メソッドを使用して行う。
まず、ConnectionインターフェイスのsetAutoCommit()メソッドにfalseを渡すことで、オートコミットをオフにし、トランザクションモードを開始する。
コミットはConnectionインターフェイスのcommit()メソッド、ロールバックはrollback()メソッドで行う。
また、先ほどの例のように「エラー時にはロールバックする」場合には、finallyブロック内でrollback()メソッドを呼んでから、各close()を呼び出すようにする。
トランザクションは厳密な業務処理では必須のため、完全に理解して使いこなせるようにしておくこと。
コミットやロールバックの他にも、FOR UPDATEを使用した排他にも使用したりと、使い道は多い。
参考サイト
// Sample.java
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Sample
{
public static void main( String[] args )
{
Connection conn = null;
PreparedStatement psCreate = null;
PreparedStatement psInsert = null;
PreparedStatement psDelete = null;
Statement stmt = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
try
{
// この使用例の使用方法についてはSQLの項目を参照してください。
// まずJDBCドライバを読み込みます。
Class.forName( "org.hsqldb.jdbcDriver" );
// JDBCに接続してコネクションを取得します。
String url = "jdbc:hsqldb:mem:aname";
String user = "sa";
String password = "";
conn = DriverManager.getConnection( url, user, password );
// トランザクションモードを開始します。
conn.setAutoCommit( false );
// テスト用テーブルを作ります。
psCreate = null;
final String SQL_CREATE = "CREATE TABLE TABLE_TEST( NAME VARCHAR, VALUE INT );";
psCreate = conn.prepareStatement( SQL_CREATE );
psCreate.execute();
// そのテーブルに3行INSERTします。
final String SQL_INSERT = "INSERT INTO TABLE_TEST ( NAME, VALUE ) VALUES( ?, ? );";
psInsert = conn.prepareStatement( SQL_INSERT );
for( int iF1 = 0; iF1 < 3; ++iF1 )
{
psInsert.setString( 1, "ネーム" + iF1 );
psInsert.setInt( 2, iF1 );
psInsert.execute();
}
// コミットします。
conn.commit();
// INSERTしたデータをSELECTでクエリーします。
stmt = conn.createStatement();
final String SQL_SELECT = "SELECT NAME, VALUE FROM TABLE_TEST;";
rs1 = stmt.executeQuery( SQL_SELECT );
while( rs1.next() )
{
String name = rs1.getString( "NAME" );
int value = rs1.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム1, 1
// ネーム2, 2
// このように、INSERTした内容が確定されました。
// 行を削除します。
final String SQL_DELETE = "DELETE FROM TABLE_TEST WHERE NAME = ?;";
psDelete = conn.prepareStatement( SQL_DELETE );
psDelete.setString( 1, "ネーム1" );
psDelete.execute();
// 削除されたか、もう一度検索してみます。
rs2 = stmt.executeQuery( SQL_SELECT );
while( rs2.next() )
{
String name = rs2.getString( "NAME" );
int value = rs2.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// このように削除されました。
// ロールバックします。
conn.rollback();
// ロールバックされたか、さらに検索してみます。
rs3 = stmt.executeQuery( SQL_SELECT );
while( rs3.next() )
{
String name = rs3.getString( "NAME" );
int value = rs3.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// ネーム1, 1
// このように、削除された「ネーム1」の行が元に戻っています。
// でも行の順番は変わっていますが。このことからも、
// テーブル内での行の位置は不定だということが分かると思います。
// 任意の順番で取得したい場合にはORDER BYを使用してください。
}
catch( SQLException e )
{
// SQLの実行で問題があった場合に投げられます。
e.printStackTrace();
}
catch( ClassNotFoundException e )
{
// JDBCドライバが存在しなかった場合に投げられます。
e.printStackTrace();
}
finally
{
if( rs1 != null )
{
try
{
rs1.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs2 != null )
{
try
{
rs2.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs3 != null )
{
try
{
rs3.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( stmt != null )
{
try
{
stmt.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psDelete != null )
{
try
{
psDelete.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psInsert != null )
{
try
{
psInsert.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psCreate != null )
{
try
{
psCreate.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( conn != null )
{
try
{
conn.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
}
}
}
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Sample
{
public static void main( String[] args )
{
Connection conn = null;
PreparedStatement psCreate = null;
PreparedStatement psInsert = null;
PreparedStatement psDelete = null;
Statement stmt = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
try
{
// この使用例の使用方法についてはSQLの項目を参照してください。
// まずJDBCドライバを読み込みます。
Class.forName( "org.hsqldb.jdbcDriver" );
// JDBCに接続してコネクションを取得します。
String url = "jdbc:hsqldb:mem:aname";
String user = "sa";
String password = "";
conn = DriverManager.getConnection( url, user, password );
// トランザクションモードを開始します。
conn.setAutoCommit( false );
// テスト用テーブルを作ります。
psCreate = null;
final String SQL_CREATE = "CREATE TABLE TABLE_TEST( NAME VARCHAR, VALUE INT );";
psCreate = conn.prepareStatement( SQL_CREATE );
psCreate.execute();
// そのテーブルに3行INSERTします。
final String SQL_INSERT = "INSERT INTO TABLE_TEST ( NAME, VALUE ) VALUES( ?, ? );";
psInsert = conn.prepareStatement( SQL_INSERT );
for( int iF1 = 0; iF1 < 3; ++iF1 )
{
psInsert.setString( 1, "ネーム" + iF1 );
psInsert.setInt( 2, iF1 );
psInsert.execute();
}
// コミットします。
conn.commit();
// INSERTしたデータをSELECTでクエリーします。
stmt = conn.createStatement();
final String SQL_SELECT = "SELECT NAME, VALUE FROM TABLE_TEST;";
rs1 = stmt.executeQuery( SQL_SELECT );
while( rs1.next() )
{
String name = rs1.getString( "NAME" );
int value = rs1.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム1, 1
// ネーム2, 2
// このように、INSERTした内容が確定されました。
// 行を削除します。
final String SQL_DELETE = "DELETE FROM TABLE_TEST WHERE NAME = ?;";
psDelete = conn.prepareStatement( SQL_DELETE );
psDelete.setString( 1, "ネーム1" );
psDelete.execute();
// 削除されたか、もう一度検索してみます。
rs2 = stmt.executeQuery( SQL_SELECT );
while( rs2.next() )
{
String name = rs2.getString( "NAME" );
int value = rs2.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// このように削除されました。
// ロールバックします。
conn.rollback();
// ロールバックされたか、さらに検索してみます。
rs3 = stmt.executeQuery( SQL_SELECT );
while( rs3.next() )
{
String name = rs3.getString( "NAME" );
int value = rs3.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// ネーム1, 1
// このように、削除された「ネーム1」の行が元に戻っています。
// でも行の順番は変わっていますが。このことからも、
// テーブル内での行の位置は不定だということが分かると思います。
// 任意の順番で取得したい場合にはORDER BYを使用してください。
}
catch( SQLException e )
{
// SQLの実行で問題があった場合に投げられます。
e.printStackTrace();
}
catch( ClassNotFoundException e )
{
// JDBCドライバが存在しなかった場合に投げられます。
e.printStackTrace();
}
finally
{
if( rs1 != null )
{
try
{
rs1.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs2 != null )
{
try
{
rs2.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs3 != null )
{
try
{
rs3.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( stmt != null )
{
try
{
stmt.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psDelete != null )
{
try
{
psDelete.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psInsert != null )
{
try
{
psInsert.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psCreate != null )
{
try
{
psCreate.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( conn != null )
{
try
{
conn.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
}
}
}
// Sample.java
import java.sql.DriverManager;
import java.sql.Connection;
import java.sql.Statement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class Sample
{
public static void main( String[] args )
{
Connection conn = null;
PreparedStatement psCreate = null;
PreparedStatement psInsert = null;
PreparedStatement psDelete = null;
Statement stmt = null;
ResultSet rs1 = null;
ResultSet rs2 = null;
ResultSet rs3 = null;
try
{
// この使用例の使用方法についてはSQLの項目を参照してください。
// まずJDBCドライバを読み込みます。
Class.forName( "org.hsqldb.jdbcDriver" );
// JDBCに接続してコネクションを取得します。
String url = "jdbc:hsqldb:mem:aname";
String user = "sa";
String password = "";
conn = DriverManager.getConnection( url, user, password );
// トランザクションモードを開始します。
conn.setAutoCommit( false );
// テスト用テーブルを作ります。
psCreate = null;
final String SQL_CREATE = "CREATE TABLE TABLE_TEST( NAME VARCHAR, VALUE INT );";
psCreate = conn.prepareStatement( SQL_CREATE );
psCreate.execute();
// そのテーブルに3行INSERTします。
final String SQL_INSERT = "INSERT INTO TABLE_TEST ( NAME, VALUE ) VALUES( ?, ? );";
psInsert = conn.prepareStatement( SQL_INSERT );
for( int iF1 = 0; iF1 < 3; ++iF1 )
{
psInsert.setString( 1, "ネーム" + iF1 );
psInsert.setInt( 2, iF1 );
psInsert.execute();
}
// コミットします。
conn.commit();
// INSERTしたデータをSELECTでクエリーします。
stmt = conn.createStatement();
final String SQL_SELECT = "SELECT NAME, VALUE FROM TABLE_TEST;";
rs1 = stmt.executeQuery( SQL_SELECT );
while( rs1.next() )
{
String name = rs1.getString( "NAME" );
int value = rs1.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム1, 1
// ネーム2, 2
// このように、INSERTした内容が確定されました。
// 行を削除します。
final String SQL_DELETE = "DELETE FROM TABLE_TEST WHERE NAME = ?;";
psDelete = conn.prepareStatement( SQL_DELETE );
psDelete.setString( 1, "ネーム1" );
psDelete.execute();
// 削除されたか、もう一度検索してみます。
rs2 = stmt.executeQuery( SQL_SELECT );
while( rs2.next() )
{
String name = rs2.getString( "NAME" );
int value = rs2.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// このように削除されました。
// ロールバックします。
conn.rollback();
// ロールバックされたか、さらに検索してみます。
rs3 = stmt.executeQuery( SQL_SELECT );
while( rs3.next() )
{
String name = rs3.getString( "NAME" );
int value = rs3.getInt( "VALUE" );
System.out.println( name + ", " + value );
}
// ネーム0, 0
// ネーム2, 2
// ネーム1, 1
// このように、削除された「ネーム1」の行が元に戻っています。
// でも行の順番は変わっていますが。このことからも、
// テーブル内での行の位置は不定だということが分かると思います。
// 任意の順番で取得したい場合にはORDER BYを使用してください。
}
catch( SQLException e )
{
// SQLの実行で問題があった場合に投げられます。
e.printStackTrace();
}
catch( ClassNotFoundException e )
{
// JDBCドライバが存在しなかった場合に投げられます。
e.printStackTrace();
}
finally
{
if( rs1 != null )
{
try
{
rs1.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs2 != null )
{
try
{
rs2.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( rs3 != null )
{
try
{
rs3.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( stmt != null )
{
try
{
stmt.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psDelete != null )
{
try
{
psDelete.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psInsert != null )
{
try
{
psInsert.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( psCreate != null )
{
try
{
psCreate.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
if( conn != null )
{
try
{
conn.close();
}
catch( SQLException e )
{
// 各close()メソッドからもSQLException例外が
// 投げられるので、拾っておきます。
e.printStackTrace();
}
}
}
}
}




