1. ホーム
  2. java

[解決済み] トランザクションがロールバックのみとマークされた:原因を見つけるにはどうすればよいですか?

2022-02-12 09:59:06

質問内容

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. メソッドBのコンテキストは、例外の中で完全に欠落しています - これは大丈夫だと思いますが?
  2. methodB()内の何かが、トランザクションをロールバック専用とマークしたのでしょうか?どのように私はそれを見つけることができますか?例えば、次のようなことを確認する方法はありますか? getCurrentTransaction().isRollbackOnly()? - このように、手順を踏んで原因を探っていくことができました。

どのように解決するのですか?

ようやく問題が理解できた。

methodA() {
    methodB()
}

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

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

どうなるかというと、せっかく methodB が正しいアノテーションを持つ場合、その methodC はしない。例外が発生した場合、2番目の @Transactional は最初のトランザクションをとにかくロールバック専用にすることを意味する。