125 votes

Pourquoi la session ouverte d'Hibernate en vue est-elle considérée comme une mauvaise pratique ?

Et quel type de stratégies alternatives utilisez-vous pour éviter les LazyLoadExceptions ?

Je comprends que la session ouverte en vue a des problèmes avec :

  • Applications en couches fonctionnant dans des jvm différents
  • Les transactions ne sont engagées qu'à la fin, et il est fort probable que vous souhaitiez obtenir les résultats avant.

Mais si vous savez que votre application est exécutée sur un seul vm, pourquoi ne pas soulager votre peine en utilisant une session ouverte dans la stratégie de vue ?

47voto

Robert Munteanu Points 31558

En effet, l'envoi de Proxies éventuellement non initialisés, en particulier de collections, dans la couche de vue et le déclenchement du chargement d'Hibernate à partir de là peuvent être troublants tant du point de vue des performances que de la compréhension.

Comprendre :

L'utilisation d'OSIV "pollue" la couche de vue avec des préoccupations liées à la couche d'accès aux données.

La couche de visualisation n'est pas préparée à gérer un HibernateException ce qui peut arriver lors d'un chargement paresseux, mais vraisemblablement la couche d'accès aux données l'est.

Performance :

OSIV a tendance à ignorer le chargement correct des entités - vous avez tendance à ne pas remarquer que vos collections ou entités sont initialisées paresseusement ( peut-être N+1 ). Plus de commodité, moins de contrôle.


Mise à jour : voir L'anti-modèle OpenSessionInView pour une discussion plus large sur ce sujet. L'auteur énumère trois points importants :

  1. chaque initialisation paresseuse vous obtiendra une requête, ce qui signifie que chaque entité aura besoin de N + 1 requêtes, où N est le nombre d'associations paresseuses. Si votre écran présente des données tabulaires, la lecture du journal d'Hibernate est un gros indice que vous ne faites pas comme il faut
  2. cela va complètement à l'encontre de l'architecture en couches, puisque vous vous salissez les ongles avec la DB dans la couche de présentation. Il s'agit d'un contre-sens conceptuel, je pourrais donc m'en accommoder, mais il y a un corollaire
  3. enfin, si une exception se produit lors de la récupération de la session, elle se produira pendant l'écriture de la page : vous ne pouvez pas présenter une page d'erreur propre à l'utilisateur et la seule chose que vous pouvez faire est d'écrire un message d'erreur dans le corps de la page.

24voto

Bozho Points 273663
  • les transactions peuvent être engagées dans la couche service - les transactions ne sont pas liées à OSIV. C'est la Session qui reste ouvert, pas une transaction - en cours.

  • si vos couches d'applications sont réparties sur plusieurs machines, alors vous avez pratiquement ne peut pas utiliser OSIV - vous devez initialiser tout ce dont vous avez besoin avant d'envoyer l'objet sur le fil.

  • OSIV est un moyen agréable et transparent (c'est-à-dire qu'aucune partie de votre code n'est consciente de ce qui se passe) d'exploiter les avantages du chargement paresseux en termes de performances.

14voto

Geoffrey Wiseman Points 1315

Je ne dirais pas qu'ouvrir une session en vue est considéré comme une mauvaise pratique ; qu'est-ce qui vous donne cette impression ?

Open-Session-In-View est une approche simple de la gestion des sessions avec Hibernate. Parce qu'elle est simple, elle est parfois simpliste. Si vous avez besoin d'un contrôle fin de vos transactions, par exemple si vous avez plusieurs transactions dans une requête, Open-Session-In-View n'est pas toujours une bonne approche.

Comme d'autres l'ont souligné, l'OSIV présente certains inconvénients : vous êtes beaucoup plus exposé au problème du N+1, car vous avez moins de chances de vous rendre compte des transactions que vous déclenchez. En même temps, cela signifie que vous n'avez pas besoin de changer votre couche de service pour vous adapter à des changements mineurs dans votre vue.

5voto

0sumgain Points 502

Si vous utilisez un conteneur d'inversion de contrôle (IoC) tel que Spring, vous pouvez vous documenter sur cadrage des haricots . Essentiellement, je demande à Spring de me donner une Hibernate Session dont le cycle de vie s'étend sur toute la requête (c'est-à-dire qu'il est créé et détruit au début et à la fin de la requête HTTP). Je n'ai pas à me soucier de LazyLoadException ni la fermeture de la session puisque le conteneur IoC gère cela pour moi.

Comme nous l'avons mentionné, vous devrez penser aux problèmes de performance du SELECT N+1. Vous pouvez toujours configurer votre entité Hibernate après coup pour effectuer un chargement de jointure rapide dans les endroits où les performances posent problème.

La solution du bean scoping n'est pas spécifique à Spring. Je sais que PicoContainer offre la même capacité et je suis sûr que d'autres conteneurs IoC matures offrent quelque chose de similaire.

4voto

Davide Points 41

D'après ma propre expérience, OSIV n'est pas si mal. Le seul arrangement que j'ai fait est d'utiliser deux transactions différentes : - la première, ouverte dans la "couche service", où se trouve la "logique métier". - la seconde, ouverte juste avant le rendu de la vue

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