4

主に Jboss Forge によって生成されたアプリケーションで Jboss 7.1.1 を使用していますが、すべてのドメイン関連コードのリポジトリ レイヤーを追加しました。

データベースの状態を初期化するスタートアップ Bean を作成しようとしていました。そのために既存のリポジトリを使用したいと思います。

私のリポジトリにはすべて、拡張された PersistenceContext が注入されています。@ConversationScoped @Stateful Bean である View Bean からこれらを使用します。拡張コンテキストを使用することで、エンティティは会話中に管理されたままになります。

最初にこれを試しました:

@Startup
@Singleton
public class ConfigBean {

    @Inject
    private StatusRepository statusRepository;

    @Inject
    private ZipCode zipCodeRepository;

    @PostConstruct
    public void createData() {
        statusRepository.add(new Status("NEW"));
        zipCodeRepository.add(new ZipCode("82738"));
    }

}

Example repository:
@Stateful
public class ZipCodeRepository {

    @PersistenceContext(PersistenceContextType.EXTENDED)
    private EntityManger em;

    public void add(ZipCode zipCode) {
        em.persist(zipCode);
    }

    ....
}

これにより、アプリケーションの起動時に javax.ejb.EJBTransactionRolledbackException がスローされ、次のメッセージが表示されます。

JBAS011437: SFSB 呼び出しコール スタックで拡張永続コンテキストが見つかりましたが、トランザクションに関連付けられたトランザクション コンテキストが既にあるため、使用できません。これは、アプリケーション コードを変更して、拡張永続コンテキストまたはトランザクション コンテキストを削除することで回避できます。JPA 仕様 2.0 セクション 7.6.3.1 を参照してください。

これについての適切な説明を見つけるのに苦労しましたが、実際には、EJB とその注入はプロキシによって処理されるため、PersistenceContext の注入と伝播はすべて自動的に処理されると考えました。私は間違っていたと思います。

ただし、この考えの過程で、次のことを試しました。

@Startup
@Singleton
public class ConfigBean {

    @Inject
    private SetupBean setupBean;

    @PostConstruct
    public void createData() {
        setupBean.createData();
    }

    @Stateful
    @TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
    public static class SetupBean {

        @Inject
        private StatusRepository statusRepository;

        @Inject
        private ZipCode zipCodeRepository;

        public void createData() {
            statusRepository.add(new Status("NEW"));
            zipCodeRepository.add(new ZipCode("82738"));
        }
    }
}

これでうまくいきます。私がしたことは、Singleton Bean の静的内部クラスである Stateful SessionBean にコードをラップすることだけでした。

誰もこの行動を理解していますか?現在はすべてが機能していますが、なぜこのように機能するのかについては、まだ少し疎遠になっているからです。

4

1 に答える 1

3
  • コンテナー管理の拡張永続コンテキストは、ステートフル セッション Bean のスコープ内でのみ開始できます。これは、タイプ PersistenceContextType.EXTENDED のエンティティーマネージャーへの依存を宣言するステートフルセッション Bean が作成された時点から存在し、ステートフルセッション Bean にバインドされていると言われます。

投稿されたコードから、それZipCodeRepository自体はステートフル Bean ではないようですが、そのような Bean の 1 つから呼び出しています。

この場合、 & を介して&PersistenceContextType.TRANSACTIONから開始し、トランザクションに参加しようとするため、例外が発生します。ConfigBeanZipCodeRepositoryPersistenceContextType.EXTENDED

  • PersistenceContext-Type.EXTENDED で定義されたエンティティ マネージャを呼び出すと、そのコンポーネントにバインドされた既存の拡張永続コンテキストが使用されます。

  • ステートフル セッション Bean のビジネス メソッドが呼び出されるときに、ステートフル セッション Bean がコンテナ管理のトランザクション境界を使用し、エンティティ マネージャがまだ現在の JTA トランザクションに関連付けられていない場合、コンテナはエンティティ マネージャを現在の JTA トランザクションに関連付けて呼び出します。 EntityManager.joinTransaction。JTA トランザクションにすでに関連付けられている別の永続化コンテキストがある場合、コンテナーは EJBException をスローします。

後のケースでは、ステートフル Bean であるため、拡張タイプのSetupBean呼び出しごとに新しいトランザクションを作成しています。TransactionAttributeType.REQUIRES_NEW

したがって、SetupBean呼び出しごとに新しいトランザクションを開始するステートフル セッション Bean として追加し、後で呼び出しZipCodeRepositoryても、例外は発生しません。ZipCodeRepositoryは によって開始されたのと同じトランザクションに参加しSetupBeanます。

于 2013-03-05T08:26:03.243 に答える