2017-02-16 3 views
1

Rollback est fait ici comme prévu:Grails (2.3) @Transactional ne pas rollback

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test1() { 
    def dummy = new Dummy(name: "test1") 
    dummy.save() 
    throw new RuntimeException("test1!") 
} 

Mais pas ici - ce qui est probablement faux - try/catch ne devrait pas affecter le comportement:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test2() { 
    def dummy = new Dummy(name: "test2") 
    dummy.save() 
    try { 
    throw new RuntimeException("test2!") 
    } catch (all) { 
    println all.message 
    } 
} 

Répondre

1

peut-être vous avez mal compris le but de la capture d'essayer ou vous êtes peut-être juste d'avoir un moment bancal:

@Transactional(propagation = Propagation.REQUIRES_NEW) 
def test2() { 
    //you may be doing other stuff here 
    //but now about to do some transaction work 
    //so lets wrap this method around a try catch 
    try { 
    //this is happening 
    def dummy = new Dummy(name: "test2") 
    dummy.save()  
    } catch (Exception all) { // or catch (Throwable all) { 
    // if something went wrong in above save method 
    //should be caught and runtime exception means roll back 
    throw new RuntimeException("test2!" +all?.toString()) 
    } 
} 

Je l'espère explique où vous vous êtes trompé, mais vous voulez vraiment faire tout cela dans un service et faire l'effort d'attraper une partie dans le contrôleur -

afin que vous fassiez votre travail de transaction et si les choses tournent mal, vous pouvez ajouter des exceptions supplémentaires le service que l'essaie attrapait dans le contrôleur capturerait et le mettrait en arrière.

I did a sample project years back here espère que cela aide

Eitherway ce sont les expériences de quelqu'un et ne sont pas vraiment la façon dont vous le faire de bon codage, je veux dire qu'il est une façon inhabituelle plutôt étrange de faire les choses et en bref, il est juste en essayant de le faire lancer une exception d'exécution, ce qui déclenche l'annulation. Je m'en tiens à ma suggestion dans la réponse que vous voulez faire un coup d'essai dans le contrôleur. Cela tente de capturer les deux erreurs de validation de l'objet en question ainsi que les échecs dans l'échec de tout travail transactionnel de service donné. Something like this mais probablement beaucoup plus de travail pour capturer tous les problèmes spécifiques et revenir à la page d'origine avec les problèmes sous-jacents - ayant également maintenant annulé la transaction.

+0

Je m'attendais à ce que le proxy reconnaisse l'exception quand même. Voir test 2 ici: http://devhobbs.blogspot.de/2015/04/grailsgorm-transactions.html (résultat du test 2: aucun enregistrement écrit, l'annulation est annulée) –

+0

pour être clair, vous êtes dans un service? '@Transactional (propagation = Propagation.REQUIRES_NEW) def test1() {' est dans un service?plutôt que le contrôleur puisque si vous regardez l'exemple que vous avez fourni '@Transactionalclass BookService {' – Vahid

+0

J'ai mis à jour ma réponse depuis mon commentaire sur votre exemple etc allait être trop long vérifier la réponse mise à jour – Vahid

2

Par défaut, @Transactional enveloppe la méthode de telle sorte que toute exception non vérifiée (à savoir RuntimeException) provoque l'annulation de la transaction.

Si vous attrapez/gérez l'exception dans la méthode, bien sûr, l'exception ne se propage pas jusqu'à l'encapsuleur transactionnel et la transaction ne sera pas marquée comme rollback-only. Cela semble être ce que vous faites.

Il convient de souligner que vous pouvez indiquer que l'encapsuleur transactionnel doit annuler les transactions si d'autres exceptions sont levées (et propagées à l'encapsuleur). Vous pouvez le faire avec le paramètre d'annotation rollbackFor.

Par exemple,

@Transactional(rollbackFor=Throwable.class) 
void doTransactionalWork() throws MyException { ... } 

entraînera la transaction à être annulée si un Throwable se propage jusqu'à l'emballage, même ceux qui sont contrôlés (à savoir., MyException)

Cela devrait être le comportement de toute méthode @Transactional, que vous créiez une nouvelle transaction ou que vous héritiez d'un contexte transactionnel existant.