初めに
OutSystemsのWebDeveloperの認定試験勉強において、例外とトランザクションの学習をした。知識としては知っているが、きちんと試しておきたいと思ったので備忘録代わりに書き留めておくものである。
環境
Outsystems O11
Service Studio Version 11.54.37
学習していて気になった点
以下のドキュメントを呼んでいて気になった点を挙げていく。
トランザクションの開始
While processing a web request, OutSystems begins a database transaction on its first access to the database. The transaction is committed before OutSystems sends the response to the user.(Webリクエストの処理中、OutSystemsはデータベースへの最初のアクセス時にデータベーストランザクションを開始します。トランザクションは、OutSystemsがユーザーに応答を送信する前にコミットされます。)
中途半端な知識で、ActionのExceptionHandler毎にCommitとAbortを設定できると聞きかじっていたため、Action毎にトランザクションが開始されているものと思っていた。
web request毎、つまりClientAction、ScreenActionからServerActionが呼ばれた後、そのAction内で初めてデータベースへ最初のアクセスが発生したときにトランザクションが始めると理解した。web requestとあるが、Timerで呼び出された場合なども同様と考えてよさそう。
トランザクションを再度開始する
You can manage transactions explicitly through the CommitTransaction and AbortTransaction actions:
CommitTransaction: Issues a database COMMIT statement that makes effective all changes done on the database since the beginning of the current transaction. It also ends the current transaction and starts a new one. After a CommitTransaction, the action flow continues.
(現在のトランザクションの開始以降にデータベースに対して行われたすべての変更を有効にするデータベースCOMMITステートメントを発行します。また、現在のトランザクションを終了し、新しいトランザクションを開始します。CommitTransactionの後、アクションフローは続行されます。)
AbortTransaction: Issues a ROLLBACK statement that undoes all changes performed on the database since the beginning of the current transaction. It also ends the current transaction and starts a new one. After an AbortTransaction, the action flow continues.
(現在のトランザクションの開始以降にデータベースで実行されたすべての変更を元に戻すROLLBACKステートメントを発行します。また、現在のトランザクションを終了し、新しいトランザクションを開始します。AbortTransactionの後、アクションフローは続行されます。)
The transactions are always sequential, they cannot be nested.(トランザクションは常に連続しており、ネストすることはできません。)
一つの処理の中でトランザクションの開始後、そのトランザクションが終了するまで再度トランザクションを開始することはできない。
さらに、何らかの理由で例外が発生してしまった場合、CommitTransactionかAbortTransactionが実行され新たにトランザクションが開始されるため。例外をまたいでトランザクションを維持することができない。
今はまだ困ったことがないが、実装によってはここでつまずく可能性がありそうだなと感じた。
確認のため実装してみた
実装
- ParentActionはScreenActionより呼び出される
- ParentActionは例外処理をしない
- ChildActionは例外処理をし、AbortTransactionをYesに設定している
実行
ParentAction内やChildAction内で例外を発生させてみた。
①の直後で例外を発生させた場合
TestEntityへの新しいレコードは1件も追加されない。
②のActionのCreate直後で例外を発生させた場合
①と②のレコードは追加されず、③と④のレコードは追加される。
②のActionのCreate直後で例外を発生させた場合
①と②と③のレコードは追加されず、④のレコードは追加される。
④の直後で例外を発生させた場合
TestEntityへの新しいレコードは1件も追加されない。
②と③のActionのCreate直後で例外を発生させた場合
①と②と③のレコードは追加されず、④のレコードは追加される。
結果
あたりまえだが例外が発生した時点までのCreateがすべてロールバックされることを確認できた。
細かい制御を行いたい場合はSystemのCommitTransactionやAbortTransactionを使う必要がありそうだ。
まとめ
例外処理のトランザクション処理には大まかなルールがあり、ルールを理解したうえで使えば大抵の処理には対応できるが確認できた。しかし細やかな処理を書こうとするとSystemのCommitTransactionやAbortTransactionを明示して処理を書かなくてはならないことを確認できた。
ルールを頭に入れて設計・コーディングをしていきたい。