126 votes

Transaction marquée comme rollback uniquement : Comment puis-je trouver la cause

Je rencontre des problèmes pour valider une transaction dans ma méthode @Transactional :

methodA() {
    methodB()
}

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

Lorsque j'appelle methodB() depuis methodA(), la méthode réussit et je peux voir "OK" dans mes logs. Mais ensuite, je reçois

Impossible de valider la transaction JPA ; l'exception imbriquée est javax.persistence.RollbackException : Transaction marquée comme rollbackOnly org.springframework.transaction.TransactionSystemException: Impossible de valider la transaction JPA ; l'exception imbriquée est javax.persistence.RollbackException: Transaction marquée comme 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. Le contexte de methodB est complètement absent dans l'exception - ce qui est normal je suppose ?
  2. Quelque chose à l'intérieur de methodB() a marqué la transaction comme étant en mode rollback uniquement ? Comment puis-je le découvrir ? Y a-t-il par exemple un moyen de vérifier quelque chose comme getCurrentTransaction().isRollbackOnly()? - de cette manière je pourrais parcourir la méthode et trouver la cause.

8voto

aquajach Points 504

Voici une bonne explication avec des solutions : https://vcfvct.wordpress.com/2016/12/15/spring-nested-transactional-rollback-only/

1) Supprimez le @Transactional de la méthode imbriquée si le contrôle de la transaction n'est pas vraiment nécessaire. Ainsi, même en cas d'exception, elle remontera simplement et n'affectera pas les transactions.

OU :

2) si la méthode imbriquée a besoin d'un contrôle de transaction, définissez-la comme REQUIRES_NEW pour la stratégie de propagation de sorte que même si elle lance une exception et est marquée comme rollback only, l'appelant ne sera pas affecté.

6voto

Janet Points 9

Il y a toujours une raison pour laquelle la méthode imbriquée revient en arrière. Si vous ne voyez pas la raison, vous devez modifier le niveau de votre journaliseur en mode debug, où vous verrez plus de détails sur l'échec de la transaction. J'ai modifié mon logback.xml en ajoutant

ensuite j'ai obtenu cette ligne dans le journal :

La transaction participante a échoué - marquant la transaction existante comme étant rollback-only

Donc, j'ai simplement parcouru mon code pour voir où cette ligne est générée et j'ai constaté qu'il y a un bloc catch qui ne lance rien.

private Student add(Student s) {
        try {
            Student retval = studentRepository.save(s);
            return retval;
        } catch (Exception e) {

        }
        return null;
    }

1voto

rémy Points 385

Désactivez le gestionnaire de transactions dans votre Bean.xml

mettez ces lignes en commentaire, et vous verrez l'exception causant le rollback ;)

0voto

Asif Raza Points 1

Appliquez le code ci-dessous dans productRepository

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

pendant le test junit, appliquez le code ci-dessous

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

  System.out.println("mise à jour réussie ... ");
  assertTrue(i!=0);

}

cela fonctionne bien pour mon code

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X