GroovyのClosureでトランザクション

GroovyにはClosureを使ってJDBCを簡単に扱うためのクラス(groovy.sql.Sqlとgroovy.sql.DataSet)がありますが、トランザクションに関してはそれらしきものがなかったので考えてみました。

Tx.java : 実はSeasar2のRequiredInterceptorをほんのちょっぴり変えただけだったりします。AbstractTxもS2のAbstractTxInterceptorと殆ど同じ。

package nt.groovy;

import groovy.lang.Closure;
import javax.transaction.TransactionManager;

public class Tx extends AbstractTx{

    public Tx(TransactionManager transactionManager) {
        super(transactionManager);
    }
    
    public Object required(Closure closure) throws Throwable {
        boolean began = false;
        if (!hasTransaction()) {
            begin();
            began = true;
        } 
        Object ret = null;
        try {
            ret = closure.call();
            if (began) {
                commit();
            }
            return ret;
        } catch (Throwable t) {
            if (began) {
                rollback();
            }
            throw t;
        }
    }
}

Main.groovy : Closureの中にDBにアクセスする処理を書いてます。S2ContainerはDataSourceやTransactionManagerをもったTxを簡単に取得するために使っています。

package nt.groovy
import org.seasar.framework.container.factory.*
import groovy.sql.*

class Main {
    static void main(args) {
       SingletonS2ContainerFactory.init();
       container = SingletonS2ContainerFactory.container
       try {
           ds = container.getComponent("dataSource")
           tx = container.getComponent("tx")                 
           tx.required() { 
              dataSet = new Sql(ds).dataSet("dept")
              dataSet.add(["deptno":100, "dname":"ABC"])
           }
       } finally {
           SingletonS2ContainerFactory.destroy()
       }
    }
}

app.dicon : Txクラスを指定。TxにTransactionManagerが自動バインディングされる。



	
	

素直にAOPを使ったほうがいいかもしれませんがまあClosureの勉強ということで。