[Seasar-user:22007] Re: 一意制約違反発生時の更新処理について
Koichi Kobayashi
[E-MAIL ADDRESS DELETED]
2014年 12月 9日 (火) 03:48:26 JST
小林 (koichik) です。
おそらくですが、以下のドキュメントに書いてある
ことかと思います。
http://s2container.seasar.org/2.4/ja/tx.html
「トランザクションを開始した場合でも引き継いだ場合でも、
このインターセプタが適用されたメソッドが例外をスローした場合は、
例外の種類に応じてトランザクションがロールバックされるように
マークします。」
つまり、
public void foo() {
try {
bar();
} catch (...) {
...
}
}
public void bar() {
throw ...;
}
foo()とbar()の両方に宣言的トランザクションが
適用される場合、foo()でトランザクションを開始して
bar()はそのトランザクションの中で呼び出されますが、
bar()がスローする例外によってfoo()で開始した
トランザクションは「ロールバックされるようにマーク」
されます。
そのため、foo()でその例外をキャッチしても、
foo()からリターンする際にトランザクションは
ロールバックされます。
対策としては、トランザクション境界の中で呼び出される
メソッド (上記のbar()に相当) には宣言的トランザクションを
設定しないようにするか、特定の例外ではロールバックと
マークされないように設定する方法があります。
# 前者の方がよいかと思います。
後者については上記ドキュメントの「例外発生時の動作」に
説明があります。
実際に設定する場合はj2ee.diconをコピーして、
S2にバンドルされているejb3tx.diconを参考に
一意制約違反発生時の例外でロールバックしないように
設定してください。
On Mon, 8 Dec 2014 19:02:32 +0900, あきやまじろう <mayama0130 @ gmail.com> wrote:
> お世話になっております。あきやまと申します。
>
> 一意制約違反発生時の更新処理について教えてください。
>
> [動作環境]
> ・S2Container 2.4.45
> ・PostgreSQL 9.0.13
>
> 現在、以下の処理を実装しようとしていますが、
>
> 1.トランザクション開始(トランザクションA)
> 2.SELECT FOR UPDATEでAテーブルからレコードを取得
> 3.トランザクション開始(トランザクションB)
> 4.BテーブルのレコードをSELECT FOR UPDATEで取得
> →取得できなかった場合、レコードを登録
> →一意制約違反が発生した場合、レコードを更新
> 5.トランザクションBをコミット
> 6.CテーブルのレコードをSELECT FOR UPDATEで取得
> →取得できなかった場合、レコードを登録
> →一意制約違反が発生した場合、レコードを更新
> 7.トランザクションCをコミット
> 8.トランザクションAをコミット
>
> 項番4で一意制約違反が発生した場合にレコードを更新したいのですが、
> 「既にロールバックとしてマークされています」とログ出力され、更新できなくなり困っています。
> 項番1から8までをtry-catchして、項番1から再トライすれば、うまくいくのですが、
> 項番6でも一意制約違反の可能性があり、その場合try-catchをネストしないといけないので、できれば避けたいです。
> 何かいい対処方法があれば、ご教授の程よろしくお願いします。
--
{
name: "Koichi Kobayashi",
mail: "koichik @ improvement.jp",
blog: "http://d.hatena.ne.jp/koichik/",
twitter: "@koichik"
}
Seasar-user メーリングリストの案内