@Transactional
public class UserServiceImpl implements UserService {
...................
public void method1(){
try{
method2();
}catch(Exception e){
}
}
public void method2(){
}
}
public class UserServiceImpl implements UserService {
...................
public void method1(){
try{
method2();
}catch(Exception e){
}
}
@Transactional
public void method2(){
}
}
Dans le cas 1, si une exception se produit, la restauration fonctionne, mais dans le cas 2, elle ne fonctionne pas. Y a-t-il des problèmes de performances si je suis le cas1?
Dans le cas 1, @Transactional est appliqué à chaque méthode individuelle. Dans le cas 2 @Transactional n'est appliqué qu'à method2 (), pas à method1 ()
Cas 1: - Appel de method1 () -> une transaction est lancée. Lorsque method1 () appelle method2 () aucune nouvelle transaction n'est démarrée, car il y en a déjà une
Cas 2: - Appel de method1 () -> aucune transaction n'est démarrée. Lorsque method1 () appelle method2 () [~ # ~] non [~ # ~] la nouvelle transaction est démarrée. En effet, @Transactional ne fonctionne pas lors de l'appel d'une méthode à partir de la même classe. Cela fonctionnerait si vous appeliez method2 () à partir d'une autre classe.
Du manuel de référence du printemps :
En mode proxy (qui est la valeur par défaut), seuls les appels de méthode externes entrant via le proxy sont interceptés. Cela signifie que l'auto-invocation, en fait, une méthode dans l'objet cible appelant une autre méthode de l'objet cible, ne conduira pas à une transaction réelle au moment de l'exécution même si la méthode invoquée est marquée avec @Transactional. De plus, le proxy doit être complètement initialisé pour fournir le comportement attendu, vous ne devez donc pas vous fier à cette fonctionnalité dans votre code d'initialisation, c'est-à-dire @PostConstruct.
@Transactional
Sur une classe s'applique à chaque méthode du service. C'est un raccourci. En règle générale, vous pouvez définir @Transactional(readOnly = true)
sur une classe de service, si vous savez que toutes les méthodes accéderont à la couche de référentiel. Vous pouvez ensuite remplacer le comportement avec @Transactional
Sur les méthodes effectuant des modifications dans votre modèle. Les problèmes de performances entre 1) et 2) ne sont pas connus.
Supposons que vous ayez la classe suivante:
@Transactional(readOnly = true)
public class DefaultFooService implements FooService {
public Foo getFoo(String fooName) {
// do something
}
// these settings have precedence for this method
@Transactional(readOnly = false, propagation = Propagation.REQUIRES_NEW)
public void updateFoo(Foo foo) {
// do something
}
}
L'annotation @Transactional
Au niveau de la classe sera appliquée à chaque méthode de la classe.
Cependant , lorsqu'une méthode est annotée avec @Transactional
(Comme, updateFoo(Foo foo)
), cela aura priorité sur la transactionnelle paramètres définis au niveau de la classe.
Plus d'informations:
Citant de ici
L'équipe de Spring recommande que vous annotiez uniquement des classes concrètes avec l'annotation @Transactional, par opposition aux annotations d'interfaces.
Comme ce mécanisme est basé sur des mandataires, seuls les appels de méthode "externes" entrant via le mandataire seront interceptés. Cela signifie que `` l'auto-invocation '', c'est-à-dire une méthode dans l'objet cible appelant une autre méthode de l'objet cible, ne conduira pas à une transaction réelle au moment de l'exécution même si la méthode invoquée est marquée avec @Transactional!