3

次のような Seam コンポーネントで @Transactional アノテーションを使用しています。

@Name( "myComponent" )
@AutoCreate
public class MyComponent
{
    public void something() {
        ...
        doWork();
    }
    ...
    @Transactional
    protected void doWork() {
        try {
            log.debug( "transaction active: " + Transaction.instance().isActive() );
        } catch (Exception ignore) {}

        // some more stuff here that doesn't appear to be inside a transaction
    }
}

「その他のもの」セクションでは、いくつかの Hibernate エンティティを変更していますが、例外がスローされるバグがありました。例外が原因でトランザクションがロールバックされていないことに気付きました (変更されたエンティティはデータベースで変更されたままです)。そのため、「トランザクション アクティブ」ログを追加しました。このコードを実行すると、isActive() は false を返します。

足りないものはありますか?トランザクションがアクティブでないのはなぜですか?

念のため、RESTEasy アノテーションを使用してメソッド呼び出しをトリガーする別のコンポーネント内から Seam コンポーネントを使用しています。

4

1 に答える 1

6

私は Seam の仕組みに詳しくないので、この回答が当てはまらない場合は事前にお詫び申し上げます。

@Transactionalそのメソッドが であることに気付きましたprotected。これは、別の内部メソッドによって呼び出されていることを意味します。

Spring の AOP では、パブリックメソッドをマークし@Transactionalて、ラップされ、トランザクション プロキシに置き換えられます。外部クラスがpublicメソッドを呼び出すと、トランザクションを形成するプロキシが呼び出されます。外部クラスがマークされていないpublic別のメソッドを呼び出し、それがマークされている内部メソッドを呼び出す場合、プロキシはまったく呼び出されないため、トランザクションは作成されません。@Transactional

Spring では、doWork()メソッドを public に変更しても、同じ問題が発生します。プロキシ オブジェクトが呼び出されていないため、トランザクションはありません。クラス内で行われたメソッド呼び出しは、プロキシ オブジェクトへの呼び出しを行っていません。

いくつかのドキュメントをざっと読むと、Spring AOP と同様に、Seam がCGLib プロキシを使用していることがわかります。問題は、プロキシされたオブジェクト内から呼び出された場合でも、すべてのメソッドをプロキシできるかどうかです。この回答が当てはまらない場合は、時間を無駄にして申し訳ありません。

于 2011-10-27T13:55:27.347 に答える