262 votes

L'attribut Spring @Transactional fonctionne-t-il sur une méthode privée?

Si j'ai une @Transactional -annotation sur une méthode privée dans un bean Spring, l'annotation a-t-elle un effet?

Si l'annotation @Transactional est sur une méthode publique, cela fonctionne et ouvre une transaction.

 public class Bean {
  public void doStuff() {
     doPrivateStuff();
  }
  @Transactional
  private void doPrivateStuff() {

  }
}

...

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();
 

261voto

skaffman Points 197885

La réponse à votre question n'est - @Transactional n'aura pas d'effet si elle est utilisée pour annoter des méthodes privées. Le générateur de proxy ignore.

Ceci est documenté dans le Printemps Manuel chapitre 10.5.6:

Méthode de la visibilité et de l' @Transactional

Lors de l'utilisation de serveurs proxy, vous devez appliquer l' @Transactional d'annotation seulement les méthodes avec une visibilité publique. Si vous ne annoter protégé, privé ou paquet-visible méthodes avec l' @Transactional d'annotation, pas d'erreur est élevé, mais la méthode annotée ne présentent pas de le configuré transactionnelle paramètres. Envisager l' l'utilisation d'AspectJ (voir ci-dessous) si vous avez besoin d' pour annoter les non-méthodes publiques.

236voto

Ralph Points 42744

La Question n'est pas privé ou public, la question est: comment est-elle invoquée et qui AOP mise en œuvre que vous utilisez!

Si vous avez utilise (par défaut) Printemps Proxy AOP puis tous les AOP fonctionnalité provied par un Ressort (comme @Transational) ne sera prise en compte si l'appel passe par le proxy. -- C'est normalement le cas si la méthode annotée est appelé à partir d'un autre bean.

Cela a deux conséquences:

  • parce que les méthodes les plus pas être invoqué à partir d'un autre bean (à l'exception de la réflexion), leur @Transactional d'Annotation n'est pas pris en compte
  • même si la méthode est publique, mais il est appelé à partir de la même été, il ne sera pas pris en compte (cette déclaration est correcte seulement si (par défaut) Printemps Proxy AOP est utilisé).

@Voir le Printemps de Référence: Chapitre 9.6 9.6 utilisation de Proxy mécanismes

À mon humble avis vous devez utiliser le aspectJ mode, au lieu du Printemps des Procurations, qui permettra de surmonter le problème. Et le AspectJ Aspects Transactionnels sont tissés, même dans les méthodes privées (vérifié pour le Printemps 3.0).

37voto

Juha Syrjälä Points 11475

Par défaut, l' @Transactional d'attribut ne fonctionne que lors de l'appel d'une méthode annotée sur une référence obtenue à partir de applicationContext.

public class Bean {
  public void doStuff() {
    doTransactionStuff();
  }
  @Transactional
  public void doTransactionStuff() {

  }
}

Cela va ouvrir une transaction:

Bean bean = (Bean)appContext.getBean("bean");
bean.doTransactionStuff();

Ce ne sera pas:

Bean bean = (Bean)appContext.getBean("bean");
bean.doStuff();

Printemps De Référence: À L'Aide De @Transactional

Remarque: En mode proxy (qui est la valeur par défaut), seulement "externes" méthode des appels arrivant par la procuration seront interceptés. Cela signifie que 'auto-invocation", c'est à dire une méthode de l'objet cible de l'appel à une autre méthode de l'objet cible, ne vous conduira pas à une transaction au moment de l'exécution, même si la méthode invoquée est marqué avec @Transactional!

Envisager l'utilisation d'AspectJ mode (voir ci-dessous) si vous vous attendez à de l'auto-invocations à être enveloppé avec des transactions que bien. Dans ce cas, il n'y a pas de proxy en premier lieu; au lieu de cela, la classe cible sera la 'tissé' (c'est à dire son byte code sera modifié) afin de tourner @Transactional dans le comportement d'exécution sur n'importe quel type de méthode.

6voto

user536161 Points 19

Veuillez voir cette doc :

En mode proxy (qui est la valeur par défaut), seulement à l'extérieur des appels de méthode à venir à travers le proxy d'interception. Cela signifie que l'auto-invocation, en effet, une méthode de l'objet cible de l'appel d'une autre méthode de l'objet cible, ne conduira pas à une transaction au moment de l'exécution, même si la méthode invoquée est marqué avec @Transactionnelle.

Envisager l'utilisation d'AspectJ mode (voir l'attribut de mode dans le tableau ci-dessous) si vous vous attendez à de l'auto-invocations à être enveloppé avec des transactions que bien. Dans ce cas, il n'y aura pas un proxy en premier lieu; au lieu de cela, la classe cible sera tissé (qui est, de sa byte code sera modifié) dans le but de transformer @Transactionnelle dans le comportement d'exécution sur n'importe quel type de méthode.

----------------------------plus

donc, autre façon est d'utilisateur BeanSelfAware

4voto

ivy Points 3780

La réponse est non. Veuillez consulter Spring Reference: Using @Transactional :

L'annotation @Transactional peut être placée avant une définition d'interface, une méthode sur une interface, une définition de classe ou une méthode publique sur une classe.

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