web-dev-qa-db-fra.com

Quelle est la différence entre la définition de @Transactional sur la classe et la méthode

Cas 1

@Transactional
public class UserServiceImpl implements UserService {

    ...................
    public void method1(){
        try{
            method2();
        }catch(Exception e){

        }
    }
    public void method2(){

    }
}

Case2

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?

56
Anil Kumar

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.

50
niekname

@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.

37
jeromerg

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:

19
Konstantin Yovkov

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!

17
mok