4

次のユースケースをサポートするために、Java SE(Java EEまたはSpringではない)でトランザクションマネージャー( BitronixJBoss TSAtomikosなど)を使用するにはどうすればよいですか?

次のクラスがあると仮定します。

public class Dao {

    public void updateDatabase(DB db) {
        connet to db
        run a sql
    }

}

そして、次のように、そこからJavaRunnableを作成します。

public class MyRunnable extends Runnable {

    Dao dao;
    DB db;

    public MyRunnable(Dao dao, DB db) {
        this.dao=dao;
        this.db = db;
    }           

    public run() throws Exception {
        return dao.updateDatabase(db);
    }
}

これで、サービスレイヤーに別のクラスがあります。

public class Service {

    public void updateDatabases() {

        BEGIN TRANSACTION;

        ExecutorService es = Executors.newFixedThreadPool(10);

        ExecutorCompletionService ecs = new ExecutorCompletionService(es);

        List<Future<T>> futures = new ArrayList<Future<T>>(n);

        Dao dao = new Dao();

        futures.add(ecs.submit(new MyRunnable(dao, new DB("db1")));
        futures.add(ecs.submit(new MyRunnable(dao, new DB("db2")));
        futures.add(ecs.submit(new MyRunnable(dao, new DB("db3")));

        for (int i = 0; i < n; ++i) {
            completionService.take().get();
        }

       END TRANSACTION;
    }

}

また、クライアントはサーブレットまたはその他のマルチスレッド環境にすることができます。

public MyServlet extend HttpServlet {

    protected void service(final HttpServletRequest request, final HttpServletResponse response) throws IOException {

        Service service = new Service();

        service.updateDatabases();

    }

}

BEGINTRANSACTIONおよびENDTRANSACTIONパーツの正しいコードは何でしょうか?これも実現可能ですか?そうでない場合は、何を変更する必要がありますか?要件は、updateDatabases()メソッドを並行して(同時に複数のデータベースにアクセスするため)、トランザクションを維持することです。

4

3 に答える 3

3

このように、SubTxThreadを使用してAtomikosを使用して実行できるようです

//first start a tx
TransactionManager tm = ...
tm.begin();

Waiter waiter = new Waiter();

//the code that calls the first EIS; defined by you
SubTxCode code1 = ...

//the associated thread
SubTxThread thread1 = new SubTxThread ( waiter , code1 );

//the code that calls the second EIS; defined by you
SubTxCode code2 = ...

//the associated thread
SubTxThread thread2 = new SubTxThread ( waiter , code2 );

//start each thread
thread1.start();

thread2.start();

//wait for completion of all calls
waiter.waitForAll();

//check result
if ( waiter.getAbortCount() == 0 ) {
    //no failures -> commit tx
    tm.commit();
} else {
    tm.rollback();
}
于 2011-03-15T19:38:42.110 に答える
1

XA仕様では、すべてのXA呼び出しを同じスレッドコンテキストで実行することが義務付けられています。この理由を詳しく説明すると、スレッドにトランザクションブランチが作成される前にコミットが呼び出される可能性があるためです。

JBossTSのXAトランザクションでこれらの3つの呼び出しを実行する方法に興味がある場合

まず-ds.xml、データソースをとして指定していることを確認してください<xa-datasource>

InitialContext ctx = new InitialContext(parms);
UserTransaction ut = (UserTransaction) ctx.lookup("java:comp/UserTransaction");

ut.begin();

//Some Transactional Code

ut.commit();

上記のコードでは、ExecutorServiceを使用して呼び出しを並列化することはできません。

補足:それについてはよくわかりませんが、JTS / OTSは、トランザクションで複数のスレッドを共有できるようにすると主張しています。これは、ws-coordination / ws-transactionと同様のトランザクションコンテキストを伝播することによって行われ、JBossTSによってサポートされていると思います。赤いニシンかもしれませんが、時間の制約がない場合は、調査する価値があるかもしれません。

于 2011-03-13T15:56:18.697 に答える
0

君はどうでしょう

  1. BEGIN_TRANSATION:サービス内の3つのデータベースすべてに接続します。
  2. (dbオブジェクトの代わりに)ConnectionオブジェクトをMyRunnableに渡します
  3. END_TRANSACTION:commitを呼び出し、サービス内の3つの接続すべてを閉じます
于 2014-01-30T12:17:52.217 に答える