https://www.thatjeffsmith.com/archive/2025/02/sessionless-transactions-in-database-23ai-your-rest-apis/
セッションレス・トランザクション!? なんだろうと思ったので上記の記事を読んで、自分でも動作を確認してみました。
Oracle Databaseのトランザクションは基本的にデータベースのセッションに紐づいていますが、セッションレス・トランザクションはセッションと切り離すことができます。
セッションレス・トランザクションを使うと、Oracle REST Data Servicesの連続したREST API呼び出しをひとつのデータベース・トランザクションに含めることができます。
テストに使用したAPEXアプリケーションは以下のように動作します。
ボタンStart, Update, Commit, Rollbackはそれぞれ、1回のREST API呼び出しに対応しています。
ボタンStartをクリックしセッションレス・トランザクションを開始します。呼び出したブラウザにXID - トランザクションIDを返します。ボタンUpdateではそのXIDとTextに入力した文字列を引数として、REST API経由で表TEST_SESSIONLESS_TXに文字列を書き込みます。
連続した文字列の書き込みは、ボタンCommitのクリックで確定します。これもREST API呼び出しです。ボタンRollbackをクリックすると、それまで書き込まれた文字列はロールバックされます。
REST APIやSQLclのセッションからはDBMS_TRANSACTION.SUSPEND_TRANSACTIONを呼び出すことができますが、Oracle APEXのプロセスからDBMS_TRANSACTION.SUSPEND_TRANSACTIONを呼び出すと、処理がハングします。Oracle APEXに埋め込まれたSQLはDBMS_SQL(正確にはDBMS_SYS_SQL)パッケージを呼び出して実行されるので、一般的なセッションとは扱いが異なることがハングする理由だと思われます。そのため、セッションレス・トランザクションは概ねOracle REST Data ServicesのREST APIとともに使用することになると思われます。
以下より、上記のサンプル・アプリケーションの実装について簡単に紹介します。
ボタンUpdateをクリックしたときにデータを挿入する表をTEST_SESSIONLESS_TXとして作成しています。画面下に配置されたクラシック・レポートのソースです。
セッションレス・トランザクションを開始、再開するには、DBMS_TRANSACTION.START_TRANSACTIONを呼び出します。
ボタンStart、Update、Commit、Rollbackの処理に対応するファンクションやプロシージャを組み込んだパッケージTEST_SESSIONLESS_TX_PKGを作成します。
ファンクションSTART_TXがボタンStart、プロシージャUPDATE_TXがボタンUpdate、プロシージャCOMMIT_TXがボタンCommit、プロシージャROLLBACK_TXがボタンRollbackの処理になります。
パッケージTEST_SESSIONLESS_TX_PKGの定義部です。
パッケージTEST_SESSIONLESS_TX_PKGの本体部です。ほとんどはDBMS_TRANSACTION.START_TRANSACTIONを呼び出しセッションレス・トランザクションの開始または再開をした後に、1行データベースの操作を行っているだけです。
これらの処理を呼び出すRESTサービスを作成します。RESTサービス・モジュールとしてsessionlessを作成し、そのテンプレートとしてstart、update、commit、rollbackを作成します。テンプレートstartにはGETハンドラを作成し、それ以外はPOSTハンドラを作成します。ハンドラの処理はすべてPL/SQLで記述します。
処理内容自体は、パッケージTEST_SESSIONLESS_TX_PKGの対応するファンクションまたはプロシージャの呼び出しです。
RESTモジュールsessionlessとして作成したREST APIのブラウザからの呼び出しは、APEXアクションとして実装します。
共有コンポーネントの静的アプリケーション・ファイルとしてtest.jsを作成します。
作成したファイルtest.jsは、ページ・プロパティのJavaScriptのファイルURLに記述します。
[defer]#APP_FILES#test#MIN#.js
アプリケーションの画面を作成します。
ボタンに紐づけるAPEXアクションのコンテキストを作成するリージョンとしてControlsを作成しています。静的IDにCONTROLSを設定しています。REST API呼び出しに関わるボタンはすべてのこのリージョンに含めます。
セッションレス・トランザクションのトランザクションIDを保持するページ・アイテムとして、P1_XIDを作成しています。セッション・ステートのストレージはリクエストごと(メモリーのみ)を選択します。
ボタンSTART、UPDATE、COMMIT、ROLLBACKの動作のアクションはすべて動的アクションで定義とします。詳細のカスタム属性にdata-action=を設定し、呼び出すAPEXアクションを指定します。
ボタンUpdateをクリックしたときに表TEST_SESSIONLESS_TXに書き込む文字列を入力するページ・アイテムをP1_TEXTとして作成しています。セッション・ステートのストレージはリクエストごと(メモリーのみ)です。
ボタンREFRESHを作成し、動的アクションでクラシック・レポートのリージョンをリフレッシュしています。
ボタンUpdateをクリックして表TEST_SESSIONLESS_TXを更新しても、レポートに更新した行は現れません。ボタンCommitをクリックしてレポートをリフレッシュすると、それまでにUpdateした行が表示されます。
ボタンRESETはハウスキーピングに使用します。クリックするとプロセスRESETを呼び出し、表TEST_SESSIONLESS_TXの内容を全削除します。
プロセスRESETのソースのPL/SQLコードとして以下を記述します。
delete from test_sessionless_tx;
ボタンRESETをクリックしたときに実行されるように、サーバー側の条件のボタン押下時にRESETを指定します。
確認用のアプリケーションについての説明は以上です。
今回作成したAPEXアプリケーションのエクスポートを以下に置きました。
https://github.com/ujnak/apexapps/blob/master/exports/test-sessionless-tx.zip
Oracle APEXのアプリケーション作成の参考になれば幸いです。
完