スティルハウスの書庫の書庫

はてなダイアリーで書いてた「スティルハウスの書庫」を移転してきました。

@Transactionalでお手軽にトランザクション管理(するにはコンテナが必要でした)

Datastoreでトランザクション管理をするには、

        try {
            tx.begin();
            <更新処理>
            pm.makePersistent(members);
            tx.commit();
        } finally {
            if (tx.isActive()) {
                tx.rollback();
            }
        }

といったコードを書きます。これを毎回書くのが面倒なので、AOPやテンプレートメソッドパターン等を使ってコミットやロールバックを自動化したいところです。しかしDatastoreには、

という制限があります。トランザクションの競合を考えるとエンティティグループは小さく設計する必要があるので、必然的に1回のリクエスト内では複数のエンティティグループに更新する局面が増えます。すると、これまでのJava EEの時みたいに「1リクエスト=1トランザクション」という単純な対応付けができなくなり、リクエストの開始と終了をインターセプトして…みたいな自動化はできません。

ロジックの中で毎回上記のようなコードを書くのかうへぇ〜と思っていたら、JDOには便利な@Transactionalアノテーションがありました:

http://twistbendcoupling.net/656/spring-framework-datanucleus-jdo-

# @Transactionalで修飾したメソッド内では、PMからcurrentTransactionを取得して明示的に管理する必要はない。メソッド全域をトランザクション内で実行する場合は、PM.close()を呼ぶ必要もない。

これ使えば、

@Transactional
public void updateMyEntityGroup() {
    // 更新処理
}

みたいに書くだけで、上述のコードと同等の動きになり…そうです(まだ試してない!)。

7/18追記 Springがないとダメみたい。。

@Transactional
public void foo() {
   //
}

ってコードを書いてみましたが、メソッドの中ではTransaction#isActiveはfalseのまま。以下のページを見ると、

http://www.datanucleus.org/products/accessplatform_1_1/jdo/transactions.html

When you use a framework like Spring you would not need to specify the  tx.begin(), tx.commit(), tx.rollback()  since that would be done for you. The basic idea with  Locally Managed transactions  is that you are managing the transaction start and end. 

と書いてあって、SpringやJBossなどのコンテナがないと宣言的トランザクションまでは使えない様子。先に引用した「明示的に管理する必要はない」という説明ページも、よく読んだらSpringとDataNucleusの組み合わせ時の説明でした。しかしこれだけのためにSpring入れるのも面倒だなあ〜。残念。

MLでも聞いてみましたが、同じ結論。

http://groups.google.com/group/google-appengine-java/browse_thread/thread/da6d856650454c1b/c92aba2c96f80c5b?show_docid=c92aba2c96f80c5b#

I don't know off-hand whether it's supported by GAE's DataNucleus
plugin, but it does not appear to have anything to do with datastore
transactions, so you must use the transaction syntax in the documentation.

http://code.google.com/appengine/docs/java/datastore/transactions.html

(GAEのDataNucleusプラグインが宣言的トランザクションをサポートしているかどうかすぐには答えられないけど、Datastoreのトランザクションとは関係なさそう。ドキュメント通りに書くしかないね)