Devriez-vous placer le @Transactional
dans les DAO
classes et / ou leurs méthodes ou est-il préférable d'annoter les classes Service qui appellent à l'aide des objets DAO? Ou est-il judicieux d'annoter les deux "calques"?
java
spring
annotations
transactions
dao
Thomas Einwaller
la source
la source
En général, je suis d'accord avec les autres affirmant que les transactions sont généralement démarrées au niveau du service (en fonction de la granularité dont vous avez besoin bien sûr).
Cependant, entre-temps, j'ai également commencé à ajouter
@Transactional(propagation = Propagation.MANDATORY)
à ma couche DAO (et à d'autres couches qui ne sont pas autorisées à démarrer des transactions mais qui en ont besoin), car il est beaucoup plus facile de détecter les erreurs lorsque vous avez oublié de démarrer une transaction dans l'appelant ( par exemple le service). Si votre DAO est annoté avec une propagation obligatoire, vous obtiendrez une exception indiquant qu'il n'y a pas de transaction active lorsque la méthode est invoquée.J'ai également un test d'intégration où je vérifie tous les beans (post-processeur de bean) pour cette annotation et échoue s'il y a une
@Transactional
annotation avec propagation autre que obligatoire dans un bean qui n'appartient pas à la couche services. De cette façon, je m'assure que nous ne démarrons pas de transactions sur la mauvaise couche.la source
@Transactional
la classe d'implémentation de service et que je devrais mettre l'implémentation de classe@Transactional(propagation = MANDATORY)
DAO (référentiel)?Les annotations transactionnelles doivent être placées autour de toutes les opérations indissociables.
Par exemple, votre appel est "changer le mot de passe". Cela consiste en deux opérations
Donc, dans ce qui précède, si l'audit échoue, le changement de mot de passe doit-il également échouer? Si tel est le cas, la transaction devrait se situer autour de 1 et 2 (donc au niveau de la couche service). Si l'e-mail échoue (devrait probablement avoir une sorte de sécurité intégrée afin qu'il n'échoue pas), doit-il restaurer le mot de passe de modification et l'audit?
Voilà le genre de questions que vous devez vous poser lorsque vous décidez où placer le
@Transactional
.la source
La bonne réponse pour les architectures Spring traditionnelles est de placer la sémantique transactionnelle sur les classes de service, pour les raisons que d'autres ont déjà décrites.
Une tendance émergente au printemps est la conception basée sur le domaine (DDD). Spring Roo illustre bien la tendance. L'idée est de rendre les objets POJO du domaine beaucoup plus riches qu'ils ne le sont sur les architectures Spring typiques (généralement anémiques ), et en particulier de mettre la sémantique de transaction et de persistance sur les objets du domaine eux-mêmes. Dans les cas où tout ce qui est nécessaire est de simples opérations CRUD, les contrôleurs Web opèrent directement sur les POJO de l'objet de domaine (ils fonctionnent comme des entités dans ce contexte), et il n'y a pas de niveau de service. Dans les cas où une sorte de coordination est nécessaire entre les objets de domaine, vous pouvez avoir un handle de bean de service qui, avec
@Transaction
selon la tradition. Vous pouvez définir la propagation des transactions sur les objets de domaine sur quelque chose commeREQUIRED
pour que les objets de domaine utilisent toutes les transactions existantes, telles que les transactions qui ont été démarrées au niveau du bean de service.Techniquement, cette technique utilise AspectJ et
<context:spring-configured />
. Roo utilise des définitions inter-types AspectJ pour séparer la sémantique d'entité (transactions et persistance) de l'objet de domaine (essentiellement les champs et les méthodes métier).la source
Le cas normal serait d'annoter au niveau de la couche de service, mais cela dépend vraiment de vos besoins.
L'annotation sur une couche de service entraînera des transactions plus longues que l'annotation au niveau DAO. En fonction du niveau d'isolement des transactions, vous pouvez rencontrer des problèmes, car les transactions simultanées ne verront pas mutuellement les changements, par exemple. LECTURE RÉPÉTABLE.
L'annotation sur les DAO gardera les transactions aussi courtes que possible, avec l'inconvénient que la fonctionnalité que votre couche de service expose ne se fera pas en une seule transaction (annulable).
Il n'est pas logique d'annoter les deux couches si le mode de propagation est défini par défaut.
la source
Je place le
@Transactional
sur la@Service
couche et définitrollbackFor
toute exception etreadOnly
pour optimiser davantage la transaction.Par défaut,
@Transactional
il ne recherchera queRuntimeException
(Exceptions non vérifiées), en définissant la restauration surException.class
(Exceptions vérifiées), il restaurera toute exception.Voir Exceptions vérifiées et non vérifiées .
la source
Ou est-il judicieux d'annoter les deux "calques"? - n'est-il pas logique d'annoter à la fois la couche service et la couche dao - si l'on veut s'assurer que la méthode DAO est toujours appelée (propagée) à partir d'une couche service avec une propagation "obligatoire" dans DAO. Cela fournirait une certaine restriction pour les méthodes DAO d'être appelées à partir de la couche UI (ou des contrôleurs). De plus, lors des tests unitaires de la couche DAO en particulier, le fait d'annoter DAO garantira également qu'il est testé pour la fonctionnalité transactionnelle.
la source
propagation=Propagation.REQUIRES_NEW
. Dans le cas contraire, pour la plupart des cas, y compris propogation = obligatoire, le DAO ne fera que participer à la transaction existante lancée par la couche service.De plus, Spring recommande d'utiliser uniquement l'annotation sur les classes concrètes et non sur les interfaces.
http://static.springsource.org/spring/docs/2.0.x/reference/transaction.html
la source
Pour les transactions au niveau de la base de données
principalement utilisé
@Transactional
dans les DAO juste au niveau de la méthode, donc la configuration peut être spécifiquement pour une méthode / en utilisant par défaut (obligatoire)La méthode de DAO qui récupère les données (sélectionnez ..) - n'en avoir pas besoin
@Transactional
peut entraîner des frais supplémentaires en raison de l'intercepteur de transaction / et du proxy AOP qui doivent également être exécutés.Les méthodes de DAO qui insèrent / mettent à jour obtiendront
@Transactional
très bon blog sur transctionnel
Pour le niveau application -
j'utilise la logique transactionnelle pour la logique métier, je voudrais pouvoir effectuer un retour en cas d'erreur inattendue
la source
Transactional
inJava
Habituellement, il faut placer une transaction dans la couche service.
Mais comme indiqué précédemment, l'atomicité d'une opération est ce qui nous dit où une annotation est nécessaire. Ainsi, si vous utilisez des frameworks comme Hibernate, où une seule opération "enregistrer / mettre à jour / supprimer / ... modification" sur un objet a le potentiel de modifier plusieurs lignes dans plusieurs tables (à cause de la cascade à travers le graphe d'objet), de Bien sûr, il devrait également y avoir une gestion des transactions sur cette méthode DAO spécifique.
la source
@Transactional
Des annotations doivent être placées autour de toutes les opérations inséparables. L'utilisation de la@Transactional
propagation des transactions est gérée automatiquement. Dans ce cas, si une autre méthode est appelée par la méthode actuelle, cette méthode aura la possibilité de rejoindre la transaction en cours.Prenons donc l'exemple:
Nous avons 2 modèles c'est à dire
Country
etCity
. La cartographie relationnelleCountry
et leCity
modèle sont comme onCountry
peut avoir plusieurs villes, donc la cartographie est comme,Ici, le pays est mappé sur plusieurs villes en les récupérant
Lazily
. Alors, voici le rôle@Transactinal
lorsque nous récupérons l'objet Country de la base de données, nous obtiendrons toutes les données de l'objet Country mais n'obtiendrons pas Ensemble de villes car nous récupérons les villesLAZILY
.Lorsque nous voulons accéder à Ensemble de villes à partir de l'objet pays, nous obtiendrons des valeurs nulles dans cet ensemble car l'objet de l'ensemble créé uniquement cet ensemble n'est pas initialisé avec ses données pour obtenir les valeurs de l'ensemble que nous utilisons,
@Transactional
c'est-à-direDonc, fondamentalement, le
@Transactional
service peut effectuer plusieurs appels en une seule transaction sans fermer la connexion avec le point final.la source
@Transactional
qui est vraimentIl vaut mieux l'avoir dans la couche service! Ceci est clairement expliqué sur l'un des articles que j'ai croisé hier! Voici le lien que vous pouvez consulter!
la source
Le
@Transactional
doit être utilisé sur la couche service car il contient la logique métier. La couche DAO n'a généralement que des opérations CRUD de base de données.Doc de printemps: https://docs.spring.io/spring/docs/4.2.x/spring-framework-reference/html/transaction.html
la source
La couche de service est le meilleur endroit pour ajouter
@Transactional
annotations car la plupart de la logique métier présente ici, elle contient un comportement de cas d'utilisation au niveau de détail.Supposons que nous l'ajoutions à DAO et à partir du service, nous appelons 2 classes DAO, l'une échouée et l'autre réussie, dans ce cas si
@Transactional
n'est pas sur le service, une base de données sera validée et l'autre sera annulée.Par conséquent, ma recommandation est d'utiliser cette annotation à bon escient et d'utiliser uniquement la couche Service.
Projet Github - Java-Algos
la source
Tout d'abord, définissons où nous devons utiliser la transaction ?
Je pense que la bonne réponse est - lorsque nous devons nous assurer que la séquence d'actions sera terminée ensemble en une seule opération atomique ou qu'aucune modification ne sera apportée même si l'une des actions échoue.
Il est bien connu de mettre la logique métier dans les services. Les méthodes de service peuvent donc contenir différentes actions qui doivent être exécutées comme une seule unité logique de travail. Si tel est le cas, cette méthode doit être marquée comme transactionnelle . Bien sûr, toutes les méthodes ne nécessitent pas une telle limitation, vous n'avez donc pas besoin de marquer l'ensemble du service comme transactionnel .
Et encore plus - n'oubliez pas de prendre en compte que @Transactional peut évidemment réduire les performances de la méthode. Pour avoir une vue d'ensemble, vous devez connaître les niveaux d'isolement des transactions. Savoir que cela pourrait vous aider à éviter d'utiliser @Transactional là où il n'est pas nécessairement nécessaire.
la source
Il est préférable de conserver @Transactional dans une couche intermédiaire distincte entre DAO et Service Layer. Étant donné que la restauration est très importante, vous pouvez placer toutes vos manipulations de base de données dans la couche intermédiaire et écrire la logique métier dans la couche Service. La couche intermédiaire interagira avec vos couches DAO.
Cela vous aidera dans de nombreuses situations comme ObjectOptimisticLockingFailureException - Cette exception se produit uniquement après la fin de votre transaction. Donc, vous ne pouvez pas l'attraper dans la couche intermédiaire, mais vous pouvez maintenant l'attraper dans votre couche de service. Cela ne serait pas possible si vous avez @Transactional dans la couche Service. Bien que vous puissiez attraper le contrôleur, le contrôleur doit être aussi propre que possible.
Si vous envoyez du courrier ou des sms dans un fil séparé après avoir terminé toutes les options d'enregistrement, de suppression et de mise à jour, vous pouvez le faire en service une fois la transaction terminée dans votre couche intermédiaire. Encore une fois, si vous mentionnez @Transactional dans la couche de service, votre courrier sera envoyé même si votre transaction échoue.
Donc, avoir une couche @Transaction intermédiaire aidera à rendre votre code meilleur et facile à manipuler. Sinon, si vous utilisez dans la couche DAO, vous ne pourrez peut-être pas restaurer toutes les opérations. Si vous utilisez dans la couche Service, vous devrez peut-être utiliser AOP (Aspect Oriented Programming) dans certains cas.
la source
Idéalement, la couche Service (Manager) représente votre logique métier et, par conséquent, elle doit être annotée avec
@Transactional
.La couche Service peut appeler différents DAO pour effectuer des opérations de base de données. Supposons une situation où vous avez N nombre d'opérations DAO dans une méthode de service. Si votre première opération DAO a échoué, d'autres peuvent encore être réussies et vous finirez par un état de base de données incohérent. La couche Service d'annotation peut vous éviter de telles situations.la source
Je préfère utiliser
@Transactional
sur la couche services au niveau de la méthode.la source
@Transactional
utilise dans la couche service qui est appelée en utilisant la couche contrôleur (@Controller
) et l'appel de la couche service à la couche DAO (@Repository
), c'est-à-dire l'opération liée à la base de données.la source