web-dev-qa-db-fra.com

Méthode @Transactional appelant une autre méthode sans annotation @Transactional?

J'ai vu une méthode dans une classe Service marquée comme @Transactional, mais il appelait également d'autres méthodes de la même classe qui n'étaient pas marquées comme @Transactional.

Cela signifie-t-il que l'appel à des méthodes distinctes oblige l'application à ouvrir des connexions distinctes à la base de données ou à suspendre la transaction parente, etc.?

Quel est le comportement par défaut d'une méthode sans annotation qui est appelée par une autre méthode avec @Transactional annotation?

65
goe

Lorsque vous appelez une méthode sans @Transactional dans un bloc de transaction, la transaction parent continuera avec la nouvelle méthode. Il utilisera la même connexion que la méthode parent (avec @Transactional) et toute exception provoquée dans la méthode appelée (sans @Transactional entraînera la restauration de la transaction comme configuré dans la définition de transaction.

Si vous appelez une méthode avec un @Transactional annotation d'une méthode avec @Transactional dans la même instance, le comportement transactionnel des méthodes appelées n'aura aucun impact sur la transaction. Mais si vous appelez une méthode avec une définition de transaction à partir d'une autre méthode avec une définition de transaction, et qu'elles sont dans des instances différentes, le code de la méthode appelée suivra les définitions de transaction données dans la méthode appelée.

Vous pouvez trouver plus de détails dans la section Gestion déclarative des transactions de documentation des transactions printanières .

Le modèle de transaction déclarative Spring utilise un proxy AOP. le proxy AOP est donc responsable de la création des transactions. Le proxy AOP ne sera actif que si les méthodes avec dans l'instance sont appelées de l'extérieur de l'instance.

91
Arun P Johny
  • Cela signifie-t-il que l'appel à des méthodes distinctes oblige l'application à ouvrir des connexions distinctes à la base de données ou à suspendre la transaction parente, etc.?

Cela dépend d'un niveau de propagation . Voici tous les niveaux possibles valeurs .

Par exemple, dans le cas où un niveau de propagation est IMBRIQUÉ une transaction en cours sera "suspendue" et une nouvelle transaction sera créée ( note: création réelle de une transaction imbriquée ne fonctionnera que sur des gestionnaires de transactions spécifiques)

  • Quel est le comportement par défaut d'une méthode sans annotation qui est appelée par une autre méthode avec une annotation @Transactional?

Le niveau de propagation par défaut (ce que vous appelez "comportement") est REQUIS . Dans le cas où une méthode "intérieure" est appelée avec un @Transactional annotation dessus (ou transactionnelle déclarée via XML), elle s'exécutera dans la même transaction , par ex. "rien de nouveau" est créé.

20
tolitius

@Transactional marque la limite de la transaction (début/fin) mais la transaction elle-même est liée au thread. Une fois qu'une transaction démarre, elle se propage entre les appels de méthode jusqu'à ce que la méthode d'origine revienne et que la transaction soit validée/annulée.

Si une autre méthode est appelée qui a une annotation @Transactional, la propagation dépend de l'attribut de propagation de cette annotation.

8
sourcedelica

Vous avez peut-être deviné la réponse à votre question à partir des réponses ci-dessus. La méthode interne affectera la méthode externe si la méthode interne n'est pas annotée avec @Transactional.

Dans le cas où la méthode interne est également annotée avec @Transactional avec REQUIRES_NEW, la suite se produira.

...
@Autowired
private TestDAO testDAO;

@Autowired
private SomeBean someBean;

@Override
@Transactional(propagation=Propagation.REQUIRED)
public void outerMethod(User user) {
  testDAO.insertUser(user);
  try{
    someBean.innerMethod();
  } catch(RuntimeException e){
    // handle exception
  }
}


@Override
@Transactional(propagation=Propagation.REQUIRES_NEW)
public void innerMethod() {
  throw new RuntimeException("Rollback this transaction!");
}

La méthode interne est annotée avec REQUIRES_NEW et lève une RuntimeException afin de définir sa transaction sur rollback mais N'AFFECTERA PAS la transaction externe. La transaction externe est interrompue au début de la transaction interne, puis reprend après la conclusion de la transaction interne. Ils s'exécutent indépendamment les uns des autres, de sorte que la transaction externe PEUT être validée avec succès.

2
saran3h