83 votes

Où devrais-je placer l'annotation @Transactional: dans une définition d'interface ou dans une classe d'implémentation?

La question du titre en code:

 @Transactional (readonly = true)
public interface FooService {
   void doSmth ();
}


public class FooServiceImpl implements FooService {
   ...
}
 

contre

 public interface FooService {
   void doSmth ();
}

@Transactional (readonly = true)
public class FooServiceImpl implements FooService {
   ...
}
 

112voto

Romain Hippeau Points 16175

À partir de http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html

Le Printemps de l'équipe de recommandation est que vous ne annoter les classes de béton avec l' @Transactional d'annotation, par opposition à l'annotation des interfaces. Très certainement, vous pouvez le placer à l' @Transactional annotation sur une interface (ou une méthode d'interface), mais cela ne fonctionnera que comme vous vous attendez à si vous utilisez l'interface en fonction des procurations. Le fait que les annotations sont pas héréditaire signifie que si vous utilisez la classe de base des procurations ensuite les paramètres de la transaction ne sera pas reconnue par la classe de proxy de l'infrastructure et de l'objet ne va pas être enveloppé dans un transactionnelles proxy (ce qui serait décidément mauvais). Merci donc de ne prendre que le Printemps de l'équipe de conseils et seulement d'annoter les classes concrètes (et les méthodes des classes de béton) avec l' @Transactional d'annotation.

Remarque: ce mécanisme est basé sur les proxys, seuls les "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!

(Emphase ajoutée à la première phrase, les autres l'accent de l'original.)

9voto

AngerClown Points 3389

Vous pouvez les mettre sur l'interface mais avertissent que les transactions ne peuvent pas finir par se passe dans certains cas. Voir la deuxième astuce dans la Secion 10.5.6 du Printemps docs:

Le printemps vous recommande seulement d'annoter les classes concrètes (et les méthodes des classes de béton) avec le @Transactional annotation, par opposition à l'annotation des interfaces. Très certainement, vous pouvez le placer à l' @Transactional annotation sur une interface (ou une méthode d'interface), mais cela ne fonctionne que comme vous vous attendez à si vous utilisez l'interface en fonction des procurations. Le fait que les annotations Java ne sont pas héritées d'interfaces signifie que si vous utilisez la classe de base des serveurs mandataires (proxy-cible class="true") ou le tissage des aspects (mode="aspectj"), puis les paramètres de la transaction ne sont pas reconnus par le proxy et le tissage de l'infrastructure, et l'objet ne sera pas enveloppé dans une transactionnel proxy, ce qui serait décidément mauvais.

Je recommande de les mettre sur la mise en œuvre pour cette raison.

Aussi, pour moi, les transactions sembler un détail d'implémentation de sorte qu'ils devraient être dans la classe d'implémentation. Imaginez avoir wrapper implémentations pour l'exploitation forestière et les implémentations de test (se moque) qui n'ont pas besoin d'être à la transaction.

8voto

zmf Points 2367

Le printemps recommandation est que vous annoter les des implémentations concrètes au lieu d'une interface. Il n'est pas incorrect d'utiliser l'annotation sur une interface, il est juste possible de la mauvaise utilisation de la fonctionnalité et par inadvertance, de contourner votre @Transaction déclaration.

Si vous avez marqué quelque chose transactionnelle dans une interface, puis reportez-vous à l'un de ses mise en œuvre de classes ailleurs dans le printemps, c'est pas tout à fait évident que l'objet qui ressort crée de ne pas respecter les @Transactional annotation.

Dans la pratique, il ressemble à quelque chose comme ceci:

public class MyClass implements MyInterface { 

    private int x;

    public void doSomethingNonTx() {}

    @Transactional
    public void toSomethingTx() {}

}

0voto

engfer Points 81

Le mettre sur l'interface est acceptable tant que tous les développeurs prévisibles de votre SFI se soucient des données TX (les transactions ne sont pas des problèmes que seules les bases de données traitent). Si la méthode ne s’intéresse pas à TX (mais vous devez la mettre là pour Hibernate ou autre), mettez-la sur l’impl.

En outre, il serait peut-être préférable de placer @Transactional sur les méthodes de l'interface:

 public interface FooService {
    @Transactional(readOnly = true)
    void doSmth();
}
 

0voto

user2353505 Points 1

Veuillez regarder le lien ci-dessous qui illustre le problème avec un exemple simple mais explicatif:

http://kim.saabye-pedersen.org/2013/05/spring-annotation-on-interface-or-class.html

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