0

私の環境を簡単に説明しようとします。テクノロジー: EJB 3.1、JSF、JBoss 7.1.1

サービス クラス (@SessionScoped @Stateful) があります。サービス クラスは Dao クラスを呼び出します (@Stateless)

が欲しいです :

  • EntityManager を @StateLess Bean (Dao) にのみ使用する
  • ほとんどの場合、トランザクションが短い (持続、マージなど)
  • いくつかの多段階メソッドに対して 1 つの長いトランザクションがあります (メソッドは Dao にもあります)
  • 実際の (最新の、一次キャッシュなしの) データを持っている

私が持っている: Pesistense.xml

    <provider>org.hibernate.ejb.HibernatePersistence</provider>

    <jta-data-source>java:jboss/datasources/MydataSource</jta-data-source>
    <properties>

        <property name="hibernate.hbm2ddl.auto" value="create-drop"/>
        <property name="hibernate.dialect"value="org.hibernate.dialect.PostgreSQLDialect"/>
        <property name="hibernate.transaction.manager_lookup_class"
                  value="org.hibernate.transaction.JBossTransactionManagerLookup"/>
        <property name="hibernate.connection.autocommit" value="true"/>
        <property name="hibernate.connection.characterEncoding" value="utf8"/>

        <property name="hibernate.c3p0.min_size" value="5"/>
        <property name="hibernate.c3p0.max_size" value="20"/>
        <property name="hibernate.c3p0.timeout" value="1800"/>
        <property name="hibernate.c3p0.max_statements" value="50"/>

    </properties>

</persistence-unit>

ダオ

@Stateless
@TransactionManagement(TransactionManagementType.BEAN)
public class UserDaoBean implements UserDAO, Serializable {

    @PersistenceContext(name = "MyEntityManager")
    private EntityManager em;

     @Override
     @Transactional
 public void update(User user) throws Exception {
        User tmpUser = getUser(user.getUser());
       //some code, should be rollback, if it is an exception
        em.persist(tmpUser);

    }

トランザクションインターセプター

@Transactional
@Interceptor
public class TransactionInterceptor implements Serializable {


    @Resource
    private UserTransaction userTransaction;

    @AroundInvoke
    public Object verifyAccess(InvocationContext context) throws
            Exception {
        Object result = null;

        try {
            userTransaction.begin();
            result = context.proceed();
            userTransaction.commit();
        } catch (Exception e) {
                userTransaction.rollback();
             throw new CustomRuntimeException(e.getMessage());
        }

        return result;
    }

}

問題: Dao メソッドに例外をスローすると、完全なロールバックではなく、部分データが DB に保存されます。

EM への Join Transaction が必要だと思います。または、切断すると、各アイテムがすぐに DB に永続化されます (キャッシュを使用)。さまざまな方法を試しましたが、成功しませんでした。

よろしくお願いします!

4

1 に答える 1

0

これは特に問題があるように見えます:

<property name="hibernate.connection.autocommit" value="true"/>

ファイル内で接続管理を行うべきではありませんpersistence.xml<jta-data-source>接続情報を入れる要素と概念は<properties>相互に排他的です。

JPAプロバイダーは(プロパティを使用して)接続を作成および管理するか、(jta-data-sourceを使用して)コンテナーから接続を取得します。両方をそこに入れると、予測できない結果が得られます。JPAプロバイダーが接続プロパティを尊重することを選択した場合、トランザクション管理、接続プーリングなどを非常に簡単に停止できます。

必要なのは、これらすべてをコンテナーで構成し、永続性ユニットの宣言では何も行わないことです。

アップデート

TransactionManagementType.BEAN(BMT)との組み合わせはUserTransaction問題ないはずです。Throwableではなくキャッチしたいことに注意してくださいException。同様に、rollback()呼び出しは処理されるべき例外をスローすることもできます。ただし、全体として、これにより、必要な結果が得られるはずです。

TransactionManagementType.CONTAINERこれは(CMT)から得られるものとほぼ同じであり、インターセプターがないように見えますが、1つの重要な点で異なることに注意してください。

  • 2つのCMTBeanが同じトランザクションを共有できます
  • 2つのBMTBeanが同じトランザクションを共有することはできません。

これは、BMTを使用してBeanを呼び出す前に、コンテナが進行中の可能性のあるトランザクションを一時停止する必要があるためです。その点で、Bean管理トランザクションという用語は実際には少し誤称です。コンテナはBMTBeanを呼び出す前に進行中のトランザクションに対して常にアクションを実行するからです。

そのため、BMTとCMTは同等の立場になく、BMTなどの基本的なCMT機能の一部を実装することは実際には不可能SUPPORTSですREQUIRED

于 2012-06-18T19:30:44.817 に答える