Pourquoi utiliser @Transactionnel avec @Service à la place de @Contrôleur
J'ai vu de nombreux commentaires dans la pile de débordement articles que j'ai trouvé certaines choses à propos @Transactional utiliser avec @Service ou avec @Contrôleur
"D'habitude, on devrait mettre une transaction à la couche de service."
"Normal, ce serait le cas pour annoter sur une couche de service de niveau"
"Penser les transactions appartiennent à la couche de Service. C'est celui qui sait à propos des unités de travail et des cas d'utilisation. C'est la bonne réponse, si vous avez plusieurs DAOs injecté dans un Service qui doivent travailler ensemble en une seule transaction." [Source]
Inconvénient à utiliser @transactionnel avec @couche de service
Si j'avais 2 méthodes pour exemple saveUser() et saveEmail() (parce que je stocker les e-mails dans une base de données pour les envoyer plus tard - comme une file d'attente) je voudrais créer dans mon service une méthode saveUserAndSendEmail(Utilisateur), qui serait à la transaction. [Source]
Cela signifie que j'ai créer de nombreuses méthodes de la couche de service au lieu d'une seule Enregistrer Méthode Générique comme suit
public <T> long save(T entity) throws DataAccessException {
Session session = sessionFactory.getCurrentSession();
long getGenVal=(Long) session.save(entity);
return getGenVal;
}
Selon la solution ci-dessus , cela signifie que nous avons beaucoup de méthodes comme la suite LOL..
public <T> long saveAccount(T entity)....
public <T> long saveWithAuditLog(T entity, K entity1)....
public <T> long saveWithAuditLogAndEntries(T entity, K entity, M entity)....
De SURMONTER cette situation,
Je UTILISER LE @Transactionnelle @Contrôleur et faire un Générique de la Méthode Enregistrer et de sauvegarder toutes les entités/modèle à l'aide de cette simple méthode de sauvegarde. et si une méthode ne parviennent pas à enregistrer, puis sur toutes les transactions dans le contrôleur de la restauration avec succès.
Autre situation que vous assurer que @Transactionnelle doit être utiliser avec @Contrôleur
Dans @Controller:
pt.save(entity1);
pt.save(entity2);
int a = 2/0;
pt.save(entity3);
Dans le cas où , @Transactional sur le Service, les 2 premiers entité enregistrée avec succès mais le troisième, non pas la restauration de toutes les transactions
Dans le cas où , @Transactional sur @Contrôleur toute l'annulation de la transaction que l'exception se produire
pourquoi stack overflow a demandé , "ne pas faire de transactions dans votre contrôleur. Les mettre dans votre couche de service des classes."?
[source]
Je pense que la meilleure solution dans le cas est de créer un autre niveau de la couche entre la
controller
et la service
. Comme je vois de la controller
ne gère que les appels et les préparer vars à manipuler et à faire de la logique. Le service
gérer tous les DB choses. et le modèle de ce qui devrait être entre les controller
et la service
pouvez faire un peu de logique. Dans votre exemple faire quelques enregistre les actions, c'est une logique des actions sur les données . ce qui signifie mettre en model
et de fausser model
avec transactional
si nécessaireVotre
saveUser()
et saveEmail()
méthodes devraient être dans la couche DAO. Alors vous vous faire saveUserAndSendEmail(User user)
méthode dans la couche de Service transactionnel.
OriginalL'auteur Shahid Ghafoor | 2013-08-28
Vous devez vous connecter pour publier un commentaire.
Que vous posez sur les meilleures pratiques, et de la meilleure pratique est de marque
@Transactional
dans la couche de service en raison d'un@Controller
ne devrait pas être conscient de la persistance des données dans une logique MVC.@Service
est construit sur les cas d'utilisation généré à partir de l'analyse et sait à propos de l'unité d'ouvrages et est également réalisé à penser en termes de réutilisation: si vous passez d'un contexte web sur un ordinateur de bureau (par exemple, ou certains autres visual interface) où@Controller
couche n'existe pas, vous n'avez pas de problèmes car tout est encapsulé dans la couche de service.Un
@Service
est un contrat et une modification de la couche de présentation ne devrait pas exiger une réécriture de@Service
code.Mais le Printemps ne se soucient pas de l'endroit où vous mettez votre votre les limites de transaction, vous pouvez mettre sur
@Controller
mais votre demande peut-être plus difficile à maintenir.J'espère que c'est assez clair. Désolé si ce n'; l'anglais n'est pas ma langue maternelle.
OriginalL'auteur Luca Basso Ricci
juste pour savoir, interface annotations sont découragés
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.
OriginalL'auteur
Contrôleur est fermement dans la couche de la vue, qui peut être changé à tout moment. Le service possède encore des unités de travail et doivent fonctionner correctement, peu importe de quel point de vue est d'y accéder. Ma réponse ici est toujours debout.
saveAccount
saveAccountAudit
saveAccountAuditEntries
?OriginalL'auteur duffymo
J'ai créé une couche supérieure de service qui utilise d'autres (non-transactionnelles). Et la partie supérieure de la couche service est transactionnel.
OriginalL'auteur Yan Khonski