4 votes

Annulation de toutes les transactions imbriquées lorsque la transaction extérieure est marquée pour l'annulation.

J'ai deux méthodes annotées avec la mention @Transactional . La seconde méthode est appelée quelque part à l'intérieur de la première.

Je souhaite maintenant que le comportement suivant se produise :

  • Chaque fois que l'on entre dans la deuxième méthode imbriquée, une nouvelle méthode imbriquée est créée. doit être créée. Lorsque cette transaction est marquée pour un rollback, seule cette transaction doit être annulée.
  • Mais lorsque le transaction de la méthode extérieure est marquée pour un rollback, chaque transaction imbriquée à l'intérieur - qu'elle soit marquée pour un retour en arrière ou non - doit être annulée. doit être annulée.

Comment dois-je paramétrer le Propagation pour atteindre une telle fonctionnalité ?


P. S. : J'utilise un Gestionnaire de transactions Hibernate .

4voto

JB Nizet Points 250258

Vous devez utiliser NESTED . Notez que ce mode de propagation utilise les points de sauvegarde JDBC pour obtenir ce comportement, et que le comportement imbriqué ne fonctionne donc que si la transaction n'est qu'une enveloppe autour de la connexion JDBC. Il ne fonctionnera pas pour les transactions JTA. Voir l'article Documentation sur le printemps pour plus de détails.

1voto

dykstrad Points 41

Il convient de clarifier le comportement par défaut des transactions Java. Toutes les transactions imbriquées ne seront pas validées à moins que le parent ne le soit. Pour en savoir plus, cliquez ici http://en.wikibooks.org/wiki/Java_Persistence/Transactions

0voto

Igor F Points 1

Je proposerais d'implémenter cette fonctionnalité dans des threads séparés, c'est-à-dire que les méthodes que vous voulez lancer dans des transactions imbriquées - lancez-les simplement dans des threads séparés. Cela peut ressembler au pseudo-code suivant :

//SomeService 
// Here we start an external transaction
@Transactional
    int processAllInTransaction() {
        List<Integer> jobIds = jobService.getJobs();
        if (!jobIds.isEmpty()) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    jobIds.forEach(jobId ->
                            //Execute eveything in external transaction   
                            threadPool.execute(jobId)
                    );
                }
            }).start();

        } 
        return jobIds.size();
    }

//Method of Executor Service
void execute(final int jobId) {
    tasks.add(taskExecutor.submit(new Runnable() {
        void run() {
            someProcessor.processJob(jobId);
        }
    }));
}

//Method of another Service
@Transactional
public void processJob(int jobId) {
    //this will work in separate thransaction since was executed in another Theread
    someDao.doWorkInExternalTransaction(jobId);
}

Si vous avez vraiment besoin de contrôler les transactions externes, effectuez le travail des transactions imbriquées dans une seule transaction externe dans un nouveau Thread et attendez simplement le résultat retourné par le Thread et lancez une Exception si nécessaire.

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