2.3.1 一つのDBMSを対象にトランザクション制御を行う方法

<この項の構成>
(1) トランザクションの開始
(2) コミットとロールバック
(3) サンプルコーディング

(1) トランザクションの開始

データベースを更新する場合,クライアントからの一つの要求に対しては,必ず一つのトランザクションにすべきです。また,注意すべきことは,トランザクションはデータベース単位となる点です。複数のデータベースに対して同時にCommitやRollbackすることはできません。

簡易版クラスを使用した場合のトランザクションは,Connectメソッドを実行するとそのオブジェクトはトランザクション開始状態になります。したがって,自動コミットは利用できません。

詳細版クラスでは,明示的にトランザクションを制御する方法と自動コミットの2通りの利用方法が選択できます。

トランザクションを制御するには,DBTransactionクラスの,BeginTransメソッド,Commitメソッド,Rollbackメソッドを使用して制御します。まず,DBDriverManagerオブジェクトのTransactionメソッドを呼び出して,DBTransactionオブジェクトを生成します。このDBTransactionオブジェクトは,DBConnectionクラスのRegisterTransactionsメソッドを利用してDBConnectionオブジェクトと関連付けます。次に,DBTransactionオブジェクトのBeginTransメソッドを呼び出すか,SetAutoCommitメソッドをFALSEで呼び出すことでトランザクションを開始します。

トランザクションを使用しないでデータベースアクセスを行った場合,SQL文を一文実行するごとにコミットします(自動コミット)。これはデータベースを参照する場合にだけ利用し,データベースの更新がある場合は,必ずトランザクション制御を行ってください。

(2) コミットとロールバック

簡易版の場合,DBRDatabaseクラスのCommitメソッド,Rollbackメソッドを呼び出すことによってトランザクションが終了します。

詳細版の場合,DBTransactionオブジェクトのCommitメソッド,Rollbackメソッドを呼び出すことによりトランザクションが終了します。

トランザクションを終了させないで, データベースとの接続を切断した場合は,アプリケーションの処理が異常であると認識し,DABrokerがロールバック要求しますので注意が必要です。

(3) サンプルコーディング

コミット,及びロールバックを使用したトランザクションのサンプルコーディングを次に示します。

(例1) 簡易版クラスのトランザクション

////////////////////////////////////////////////////////////
///  クラスライブラリによるトランザクション制御(簡易版)
DBRDatabase *pDB1;
try
{
pDB1 = new DBRDatabase("DBDEF_HIR1", NULL,0);
                                      // オブジェクトの生成
 pDB1->Connect("UID","PASS",
                                      // データベースと接続
                NULL,NULL, "db01",    // データベース名
                LOCK_OPT_WAIT,0,STMT_SYNC);
                          // 自動的にトランザクションの開始
   :   // データ操作など,その他の処理
 pDB1->Commit();          // 処理が正常に終了した場合コミット
   :
}
catch(DBSQLCA e)
{
   cout << "エラーが発生しました。¥n" << e.ErrorMessage << "¥n"
                                                      << flush;
   if(e.e_SQLERROR)
   {
     cout << e.e_SQLERROR << "¥n" << flush;
                                     // エラーメッセージの取得
   pDB1->Rollback();                 // 処理中ならばロールバック
 }
  pDB1->close();                     // コネクションの解放
}

(例2) 詳細版クラスのトランザクション

////////////////////////////////////////////////////////////
///  クラスライブラリによるトランザクション制御(詳細版)

DBDriverManager*  pDrvMan;
DBDriver*  pDriver;
DBConnection* pCnct;
DBTransaction* pTrns;
 try
 {
   pDrvMan = new DBDriverManager;
                       //DBDriverManagerをnew演算子で生成
   pDrvMan->InitializeMessage();
   pDriver = pDrvMan->Driver("DBDEF_HIR1");
                                // データベース種別名の設定
   pTrns = pDrvMan->Transaction();
                          // DBTransactionオブジェクト生成
   pCnct = pDriver->Connect("Con1",      //データベース接続
                            "UserID","Password",NULL,NULL,
                            "db01",LOCK_OPT_WAIT,0,STMT_SYNC);
   pCnct->RegisterTransactions(pTrns);
                                  //オブジェクトの関連付け
   pTrns->BeginTrans();           // トランザクションの開始
   :  // データ操作など,その他の処理
   pTrns->Commit();     // 処理が正常に終了した場合コミット
   :
 }
 catch(DBSQLCA e)
 {
   cout << "エラーが発生しました。¥n" << e.ErrorMessage << "¥n"
                                                      << flush;
   if(e.e_SQLERROR)
     cout << e.e_SQLERROR << "¥n" << flush;
                                     // エラーメッセージの取得
 {
     pTrns->Rollback();            // 処理中ならばロールバック
 }
 if(pCnct)
 {
   pDriver->RemoveConnection("Con1");    // コネクションの解放
   pCnct = NULL;
}