La question n'est pas privée ou publique, la question est: comment est-elle invoquée et quelle implémentation AOP vous utilisez!
Si vous utilisez (par défaut) Spring Proxy AOP, toutes les fonctionnalités AOP fournies par Spring (comme @Transational
) ne seront prises en compte que si l'appel passe par le proxy. - C'est normalement le cas si la méthode annotée est invoquée depuis un autre bean.
Cela a deux implications:
- Étant donné que les méthodes privées ne doivent pas être appelées à partir d'un autre bean (l'exception est la réflexion), leur
@Transactional
annotation n'est pas prise en compte.
- Si la méthode est publique, mais qu'elle est invoquée à partir du même bean, elle ne sera pas prise en compte non plus (cette instruction n'est correcte que si (par défaut) Spring Proxy AOP est utilisé).
@See Spring Reference: Chapitre 9.6 9.6 Mécanismes de proxy
À mon humble avis, vous devriez utiliser le mode aspectJ, au lieu des Spring Proxies, qui résoudra le problème. Et les aspects transactionnels AspectJ sont tissés même dans des méthodes privées (vérifié pour Spring 3.0).
La réponse à votre question est non -
@Transactional
n'aura aucun effet si elle est utilisée pour annoter des méthodes privées. Le générateur de proxy les ignorera.Ceci est documenté dans le chapitre 10.5.6 du manuel Spring :
la source
Par défaut, l'
@Transactional
attribut ne fonctionne que lors de l'appel d'une méthode annotée sur une référence obtenue à partir de applicationContext.Cela ouvrira une transaction:
Cela ne va pas:
Référence Spring: utilisation de @Transactional
la source
Oui, il est possible d'utiliser @Transactional sur des méthodes privées, mais comme d'autres l'ont mentionné, cela ne fonctionnera pas hors de la boîte. Vous devez utiliser AspectJ. Il m'a fallu un certain temps pour comprendre comment le faire fonctionner. Je partagerai mes résultats.
J'ai choisi d'utiliser le tissage au moment de la compilation au lieu du tissage au temps de chargement parce que je pense que c'est une meilleure option globale. En outre, j'utilise Java 8, vous devrez donc peut-être ajuster certains paramètres.
Tout d'abord, ajoutez la dépendance pour aspectjrt.
Ajoutez ensuite le plugin AspectJ pour effectuer le tissage de bytecode réel dans Maven (ce n'est peut-être pas un exemple minimal).
Enfin, ajoutez ceci à votre classe de configuration
Vous devriez maintenant pouvoir utiliser @Transactional sur des méthodes privées.
Une mise en garde à cette approche: vous devrez configurer votre IDE pour être au courant d'AspectJ sinon si vous exécutez l'application via Eclipse par exemple, cela peut ne pas fonctionner. Assurez-vous de tester par rapport à une construction Maven directe comme test de santé mentale.
la source
Si vous devez encapsuler une méthode privée dans une transaction et que vous ne souhaitez pas utiliser aspectj, vous pouvez utiliser TransactionTemplate .
la source
TransactionTemplate
utilisation, mais veuillez appeler cette deuxième méthode..RequiresTransaction
plutôt que..InTransaction
. Nommez toujours les choses comme vous aimeriez les lire un an plus tard. Je dirais également que si cela nécessite vraiment une deuxième méthode privée: soit mettez son contenu directement dans l'execute
implémentation anonyme, soit si cela devient compliqué, cela pourrait être une indication de diviser l'implémentation en un autre service que vous pouvez ensuite annoter@Transactional
.Spring Docs explique que
Un autre moyen est l'utilisateur BeanSelfAware
la source
BeanSelfAware
? Cela ne ressemble pas à une classe de printempsLa réponse est non. Veuillez consulter Spring Reference: Using @Transactional :
la source
De la même manière que @loonis a suggéré d'utiliser TransactionTemplate, on peut utiliser ce composant d'assistance (Kotlin):
Usage:
Je ne sais pas si
TransactionTemplate
réutiliser la transaction existante ou non, mais ce code le fait certainement.la source