例外で終わったときには自動的にロールバックされる。 play1.3で、複数DB接続をサポートした影響で、トランザクション制御に影響が出ている。 分かる範囲でそれぞれ追記しておく。 アノテーションDBの更新を行わないとき、以下のアノテーションを該当のメソッドに設定することで読み出し専用にすることができる。@play.db.jpa.Transactional(readOnly=true) トランザクションの自動開始をさせたくないときは、以下のアノテーションを該当メソッド、もしくは該当コントローラクラスに設定する。 @play.db.jpa.NoTransaction トランザクションの開始JPAPlugin.startTx(false); readOnlyなトランザクションの時は、引数にtrueを指定する。 既に開始しているトランザクションは破棄される。 play1.3以降play1.3では、JPAPlugin.startTx は非推奨メソッドになっており、そのまま使うと、デフォルトのDBに対しての操作となる。今後は下記メソッドにて、DB識別名を指定して操作する。 play.db.jpa.JPA.startTx(String, boolean) デフォルトのDBであれば、JPAクラスに定義されている文字列を使って下記のように記述すればよい。 JPA.startTx(JPA.DEFAULT, false); コミットJPAPlugin.closeTx(false); 引数falseがコミットを意味する。trueならロールバックする。 JPA .closeTx(JPA.DEFAULT); ロールバックJPA.setRollbackOnly();
JPAPlugin.closeTx(true); どちらでも可能。 startTxで始まったら、closeTxを使って終わるのがスマートな気もする。 DB識別名を指定して操作する。 JPA.rollbackTx(JPA.DEFAULT); 並列トランザクションを扱う場合playframework1としては、1リクエスト1トランザクションを基本としている。 そのトランザクションはカレントのトランザクションとして、JPA.local.get(), set() でアクセスすることができる。 リクエスト処理中に例外が発生したときは、このトランザクションに対してロールバックが行われる。 幾つかのトランザクションを並列に扱うときは、カレントのトランザクションを切り替えることで実現することになる。 切替の際は、カレントのトランザクションを自前で、退避/復帰する。 新たなトランザクションはstartTxを用いて開始する。 ※play1.3.0では、複数DB利用をサポートした影響で、JPA.localプロパティが無くなってしまった。そのため、ここに書かれている方法は使えない。 退避カレントのトランザクションをtempContextに退避する。カレントトランザクションは無効にしておく。 JPA tran1 = JPA.local.get(); JPA.local.remove(); 復帰退避していたトランザクションを、カレントトランザクションに設定する。 JPA.local.set(tran1); 注意点httpリクエスト処理内で例外が発生すると、playframeworkはカレントのトランザクションに対してロールバックを行う。 単一のトランザクションの場合は問題ないが、複数のトランザクションを扱っているときは、カレント以外のトランザクションのロールバックも忘れずに行う必要がある。 play1.3以降での並列トランザクション今までは、Threadlocalで唯一のJPAコンテキストを保持する実装だった。1.3.0では複数DB接続を実現するため、ThreadlocalでDB名とJPAコンテキストのMAPオブジェクトを保持する実装になった。 退避と復帰は、DBごとに行なう。 // コンテキスト退避 JPAContext defContext = JPA.currentEntityManager.get().get(JPA.DEFAULT); JPA.currentEntityManager.get().remove(JPA.DEFAULT); // 新たなトランザクションを開始 JPA.startTx(JPA.DEFAULT, false); 復帰// トランザクションを閉じる JPA.closeTx(JPA.DEFAULT); // コンテキスト復帰 if (defContext != null) { } @Finally などで必ずトランザクションがすべて閉じられるように実装すべき。 参考:
|
playframework1 > jpa >