web-dev-qa-db-ja.com

ロールバックのみとしてマークされたトランザクション:原因を見つける方法

@Transactionalメソッド内でトランザクションをコミットする際に問題が発生しています:

methodA() {
    methodB()
}

@Transactional
methodB() {
    ...
    em.persist();
    ...
    em.flush();
    log("OK");
}

MethodA()からmethodB()を呼び出すと、メソッドは正常に渡され、ログに「OK」が表示されます。しかし、その後、私は得る

Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Transaction marked as rollbackOnly
    at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.Java:521)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.Java:754)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.Java:723)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.Java:393)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.Java:120)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.Java:172)
    at org.springframework.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.Java:622)
    at methodA()...
  1. MethodBのコンテキストは例外で完全に欠落しています-どちらが大丈夫だと思いますか?
  2. MethodB()内の何かがトランザクションをロールバックのみとしてマークしましたか?どうすれば見つけられますか?たとえば、getCurrentTransaction().isRollbackOnly()?のようなものをチェックする方法はありますか?このように、メソッドをステップスルーして原因を見つけることができます。
79
Vojtěch

私はついに問題を理解しました:

methodA() {
    methodB()
}

@Transactional(noRollbackFor = Exception.class)
methodB() {
    ...
    try {
        methodC()
    } catch (...) {...}
    log("OK");
}

@Transactional
methodC() {
    throw new ...();
}

起こるのは、methodBに正しい注釈が付いていても、methodCにはないということです。例外がスローされると、2番目の@Transactionalは最初のトランザクションをロールバックのみとしてマークします。

58
Vojtěch

メソッドを@Transactionalとしてマークすると、メソッド内で例外が発生すると、周囲のTXがロールバックのみとしてマークされます(キャッチした場合でも)。 @Transactionalアノテーションの他の属性を使用して、次のようなロールバックを防止できます。

@Transactional(rollbackFor=MyException.class, noRollbackFor=MyException2.class)
88
Ean V

原因となる例外をすばやく取得するには、再コーディングまたは再構築する必要なしにブレークポイントを設定します

org.hibernate.ejb.TransactionImpl.setRollbackOnly() // Hibernate < 4.3, or
org.hibernate.jpa.internal.TransactionImpl() // as of Hibernate 4.3

そして、通常はインターセプターに向かってスタックに上がります。そこで、キャッチブロックから原因の例外を読み取ることができます。

37
FelixJongleur42

アプリケーションの実行中にこの例外に苦労しました。

最後に問題はSQLクエリにありました。クエリが間違っていることを意味します。

クエリを確認してください。これは私の提案です

10

コードの...セクションでスローおよびキャッチされている例外を探します。ランタイムおよびロールバックアプリケーション例外は、他の場所でキャッチされた場合でも、ビジネスメソッドからスローされるとロールバックを引き起こします。

コンテキストを使用して、トランザクションにロールバックのマークが付けられているかどうかを確認できます。

@Resource
private SessionContext context;

context.getRollbackOnly();
5
Mareen

bean.xmlでtransactionmanagerを無効にします

<tx:annotation-driven proxy-target-class="true" transaction-manager="transactionManager"/>
    <bean id="transactionManager"
        class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
        <property name="dataSource" ref="dataSource"></property>
    </bean>

これらの行をコメントアウトすると、ロールバックの原因となる例外が表示されます;)

1
rémy

ソリューションの良い説明を見つけました: https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

1)トランザクション制御を実際に必要としない場合、ネストされたメソッドから@Transacionalを削除します。そのため、例外がありますが、バブルアップし、トランザクションに影響を与えることはありません。

または:

2)ネストされたメソッドがトランザクション制御を必要とする場合、例外をスローし、ロールバックのみとしてマークされている場合でも、伝播ポリシーのREQUIRE_NEWとして作成します。呼び出し元は影響を受けません。

1
aquajach

productRepositoryに以下のコードを適用します

@Query("update Product set prodName=:name where prodId=:id ") @Transactional @Modifying int updateMyData(@Param("name")String name, @Param("id") Integer id);

一方、junitテストでは以下のコードを適用します

@Test
public void updateData()
{
  int i=productRepository.updateMyData("Iphone",102);

  System.out.println("successfully updated ... ");
  assertTrue(i!=0);

}

それは私のコードでうまく機能しています

0
Asif Raza

@ Transactional importを確認してください

import javax.transaction.Transactional;
0
SHIVA