Appel de la méthode Spring @Transaction par la méthode dans la même classe, ne fonctionne pas?

Je suis nouveau à Spring Transaction. Quelque chose que j’ai trouvé vraiment étrange, probablement je l’ai bien compris. Je voulais avoir un niveau transactionnel autour de la méthode et j’ai une méthode d’appel dans la même classe et il semble que cela ne lui plaise pas, il doit être appelé depuis la classe séparée. Je ne comprends pas comment c’est possible. Si quelqu’un a une idée sur la façon de résoudre ce problème, j’apprécierais beaucoup. Je voudrais utiliser la même classe pour appeler la méthode transactionnelle annotée.

Voici le code:

public class UserService { @Transactional public boolean addUser(Ssortingng userName, Ssortingng password) { try { // call DAO layer and adds to database. } catch (Throwable e) { TransactionAspectSupport.currentTransactionStatus() .setRollbackOnly(); } } public boolean addUsers(List users) { for (User user : users) { addUser(user.getUserName, user.getPassword); } } } 

C’est une limitation de Spring AOP (objects dynamics et cglib ).

Si vous configurez Spring pour utiliser AspectJ pour gérer les transactions, votre code fonctionnera.

La solution la plus simple et probablement la meilleure consiste à modifier votre code. Par exemple, une classe qui gère les utilisateurs et un autre qui traite chaque utilisateur. Ensuite, le traitement des transactions par défaut avec Spring AOP fonctionnera.


Conseils de configuration pour la gestion des transactions avec AspectJ

Pour permettre à Spring d’utiliser AspectJ pour les transactions, vous devez définir le mode sur AspectJ:

  

Si vous utilisez Spring avec une version antérieure à 3.0, vous devez également l’append à votre configuration Spring:

    

Le problème ici est que les proxys AOP de Spring ne s’étendent pas mais enveloppent plutôt votre instance de service pour intercepter les appels. Cela signifie que tout appel à “this” à partir de votre instance de service est directement appelé sur cette instance et ne peut pas être intercepté par le proxy enveloppant (le proxy n’est même pas au courant de cet appel). Une solution est déjà mentionnée. Une autre astuce serait de faire en sorte que Spring injecte une instance du service dans le service lui-même, et appelle votre méthode sur l’instance injectée, qui sera le proxy qui gère vos transactions. Mais sachez que cela peut avoir de mauvais effets secondaires, si votre bean de service n’est pas un singleton:

   ...  public class UserService { private UserService self; public void setSelf(UserService self) { this.self = self; } @Transactional public boolean addUser(Ssortingng userName, Ssortingng password) { try { // call DAO layer and adds to database. } catch (Throwable e) { TransactionAspectSupport.currentTransactionStatus() .setRollbackOnly(); } } public boolean addUsers(List users) { for (User user : users) { self.addUser(user.getUserName, user.getPassword); } } } 

Ceci est ma solution pour l’ auto-invocation :

 private SBMWSBL self; @Autowired private ApplicationContext applicationContext; @PostConstruct public void postContruct(){ self = applicationContext.getBean(SBMWSBL.class); } 

Avec Spring 4, il est possible de s’auto-activer

 @Service @Transactional public class UserServiceImpl implements UserService{ @Autowired private UserRepositroy repositroy; @Autowired private UserService userService; @Override public void update(int id){ repository.findOne(id).setName("ddd"); } @Override public void save(Users user) { repositroy.save(user); userService.update(1)l } } 

Vous pouvez créer automatiquement BeanFactory dans la même classe et faire un

getBean(YourClazz.class)

Il va automatiquement renseigner votre classe et prendre en compte votre annotation @Transactional ou autre.

Le problème est lié à la façon dont les classes de charge de spring et les mandataires. Cela ne marchera pas, jusqu’à ce que vous écriviez votre méthode / transaction interne dans une autre classe ou que vous vous rendiez dans une autre classe, puis que vous reveniez dans votre classe, puis que vous écriviez la méthode de transposition nestede interne.

En résumé, les mandataires de spring ne permettent pas les scénarios auxquels vous faites face. vous devez écrire la deuxième méthode de transaction dans une autre classe