it-swarm.com.de

Transaktion nur als Rollback markiert: Wie finde ich die Ursache?

Ich habe Probleme beim Festschreiben einer Transaktion innerhalb meiner @ Transactional-Methode:

methodA() {
    methodB()
}

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

Wenn ich methodB () von methodA () aufrufe, wird die Methode erfolgreich übergeben und in meinen Protokollen wird "OK" angezeigt. Aber dann verstehe ich

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. Der Kontext von methodB fehlt in der Ausnahme vollständig - was ist in Ordnung, nehme ich an?
  2. Etwas innerhalb der MethodeB () hat die Transaktion nur als Rollback markiert? Wie kann ich das herausfinden? Gibt es zum Beispiel eine Möglichkeit, etwas wie getCurrentTransaction().isRollbackOnly()? zu überprüfen - so könnte ich die Methode durchgehen und die Ursache finden.
81
Vojtěch

Endlich habe ich das Problem verstanden:

methodA() {
    methodB()
}

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

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

Was passiert ist, dass das methodB die richtige Anmerkung hat, das methodC jedoch nicht. Wenn die Ausnahme ausgelöst wird, wird das zweite @Transactional markiert die erste Transaktion ohnehin nur als Rollback.

59
Vojtěch

Wenn Sie Ihre Methode als @Transactional Markieren, markiert das Auftreten einer Ausnahme in Ihrer Methode den umgebenden TX nur als Rollback (auch wenn Sie ihn abfangen). Sie können andere Attribute der Annotation @Transactional Verwenden, um ein Zurücksetzen zu verhindern:

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

Um die verursachende Ausnahme schnell abzurufen ohne dass neu codiert oder neu erstellt werden muss, setzen Sie einen Haltepunkt auf

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

und gehe in den Stapel, normalerweise zu einem Interceptor. Dort können Sie die verursachende Ausnahme von einem Catch-Block lesen.

38
FelixJongleur42

Ich hatte mit dieser Ausnahme zu kämpfen, als ich meine Anwendung ausführte.

Schließlich war das Problem bei der SQL-Abfrage . Ich meine, dass die Abfrage falsch ist.

bitte überprüfen Sie Ihre Anfrage. Das ist mein Vorschlag

10

Suchen Sie nach Ausnahmen, die in den Abschnitten ... Ihres Codes ausgelöst und abgefangen werden. Laufzeit- und Rollbackanwendungsausnahmen verursachen ein Rollback, wenn sie aus einer Geschäftsmethode entfernt werden, selbst wenn sie an einer anderen Stelle abgefangen werden.

Sie können den Kontext verwenden, um herauszufinden, ob die Transaktion für das Rollback markiert ist.

@Resource
private SessionContext context;

context.getRollbackOnly();
5
Mareen

deaktivieren Sie den Transaktionsmanager in Ihrer Bean.xml

<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>

wenn Sie diese Zeilen auskommentieren, wird die Ausnahme angezeigt, die den Rollback verursacht.

1
rémy

Fanden eine gute Erklärung mit Lösungen: https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

1) Entfernen Sie @Transacional aus der verschachtelten Methode, wenn keine Transaktionssteuerung erforderlich ist. Selbst wenn es eine Ausnahme gibt, sprudelt es nur und beeinträchtigt keine Transaktionssachen.

ODER:

2) Wenn die geschachtelte Methode keine Transaktionssteuerung benötigt, legen Sie dies als REQUIRE_NEW für die Propagierungsrichtlinie fest, auch wenn eine Ausnahme ausgelöst und nur als Rollback markiert wird. Der Aufrufer ist davon nicht betroffen.

1
aquajach

wenden Sie den folgenden Code in productRepository an

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

während des Junitests gilt folgender Code

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

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

}

es funktioniert gut für meinen Code

0
Asif Raza

bitte überprüfen Sie Ihren @ Transactional Import sollte es sein

import javax.transaction.Transactional;
0
SHIVA