jfluteの日記スマートフォン用の表示で見るjfluteの日記2009-07-23HibernateのトランザクションのトラブルVarious【概要】Hibernateのトランザクション周りで遭遇した現象を書いてみます。前提と現象のところに書いてあるのですが、現象の問題領域がJUnitの単体テストにとどまったため、バージョンを変えた場合の検証やもっと奥深く突っ込んだ検証は(業務的に)打ち切りとなりました。まとまった情報という感じではありませんが、もし他に似たような現象に遭遇した人がいたら、その人のための情報共有として。【環境】s2framework-2.4.38s2extension-2.4.38s2tiger-2.4.38s2hibernate-jpa-1.0.1.jarhibernate-3.2.7.ga.jarhibernate-annotations-3.2.1.ga.jarhibernate-entitymanager-3.2.1.ga.jar【前提】Hibernateの最新バージョンを使うとどうなるかは試してない。利用しているバージョンは逆に新しすぎるのだが、バージョンを戻しての検証はしていない。個人的にはHibernateは詳しくないので、そもそも利用の仕方に不備があるかもしれない。再度DBアクセスして(別の@RequiredTxのメソッドを呼ぶ)、その後flush()を呼び出すと例外が発生してしまう。...TxScopedEntityManagerProxy.flush(TxScopedEntityManagerProxy.java:246)トランザクションは継続されているのに「トランザクションが必要」と言われる。最後のflush()でTransactionRequiredExceptionが発生する。業務的にはここで更新がしたい}ちなみにflushをする理由は、flushをしないと最後のbar()での更新処理が実行されない現象が発生したため。これは別の問題かもしれない。呼び出し側でトランザクションを開始せずに@RequiredTxが有効になるように実行した場合は問題が発生しなかった。呼び出し側でトランザクションを開始する動機は主にJUnitからの単体テストのためであり、業務的には例外系のテストが書けない(書きにくい)というだけの問題にとどまった。「Seasarの(ドキュメントに書いてる)バージョンを戻すとどうなるか?」は確認できていない。例外発生時にコミットやロールバック処理はしないが、デフォルトではsetRollbackOnly()はするようになっている。これはSeasar-MLにて仕様と確認済み。TxRuleの設定で挙動の変更は可能。setRollbackOnly()だけはする(設定で変更可能)」という認識でいる必要がある。「adapter.setRollbackOnly()」が呼び出されると現象が発生するのか?「adapter.setRollbackOnly()」でJTAのトランザクションのStatusが「1」になる。「1」は「Status.STATUS_MARKED_ROLLBACK」である。foo()での例外発生前と発生後ではこの点だけが違う。EntityManagerの状態はOpen状態、JoinStatusもJOINEDと共に例外発生前と後で何も変わらないしかし、この違いだけでflush()メソッドの中で行っている「トランザクションの有効判定」がfalseを戻して例外となる。戻し、isTransactionInProgress()がfalseとなり、flush()時に例外となる。想定通りの実行はできた。例外発生時に変な状態でコミットされないためのセーフティネットと考えればこの回避は正しいのかどうか不明。再開したディズニーシーにはてなブログをはじめよう!jfluteさんは、はてなブログを使っています。ブログを報告するスターをつけました引用をストックしましたストック一覧を見る閉じる引用するにはまずログインしてくださいログイン閉じる引用をストックできませんでした。再度お試しください閉じる限定公開記事のため引用できません。