J'ai vu une spring.jpa.open-in-view=true
propriété dans la documentation de Spring Boot pour la configuration JPA.
- La
true
valeur par défaut de cette propriété est-elle si elle n'est pas du tout fournie ?; - Qu'est-ce que cela fait vraiment? Je n'ai trouvé aucune bonne explication à cela;
- Est-ce que ça vous fait utiliser
SessionFactory
au lieu deEntityManagerFactory
? Si oui, comment puis-je lui dire de me permettre d'utiliser à laEntityManagerFactory
place?
Merci!
java
spring
jpa
spring-boot
spring-data
Carlos Alberto
la source
la source
L'anti-modèle OSIV
Au lieu de laisser la couche de gestion décider de la meilleure manière d'extraire toutes les associations nécessaires à la couche de vue, OSIV (Open Session in View) force le contexte de persistance à rester ouvert afin que la couche de vue puisse déclencher l'initialisation du proxy, comme illustré par le schéma suivant.
OpenSessionInViewFilter
appelle laopenSession
méthode du sous-jacentSessionFactory
et obtient un nouveauSession
.Session
est lié auTransactionSynchronizationManager
.OpenSessionInViewFilter
appelsdoFilter
de lajavax.servlet.FilterChain
référence d'objet et la demande est ensuite traitéeDispatcherServlet
est appelé et achemine la requête HTTP vers le sous-jacentPostController
.PostController
appel lePostService
pour obtenir une liste d'Post
entités.PostService
ouvre une nouvelle transaction etHibernateTransactionManager
réutilise la mêmeSession
qui a été ouverte par leOpenSessionInViewFilter
.PostDAO
récupère la liste desPost
entités sans initialiser aucune association paresseuse.PostService
valide la transaction sous-jacente, maisSession
n'est pas fermé car il a été ouvert en externe.DispatcherServlet
commence le rendu de l'interface utilisateur, qui, à son tour, parcourt les associations différées et déclenche leur initialisation.OpenSessionInViewFilter
peut fermer leSession
, et la connexion à la base de données sous-jacente est également libérée.À première vue, cela ne semble pas être une chose terrible à faire, mais, une fois que vous l'avez vue du point de vue d'une base de données, une série de failles commencent à devenir plus évidentes.
La couche de service ouvre et ferme une transaction de base de données, mais par la suite, aucune transaction explicite n'est en cours. Pour cette raison, chaque instruction supplémentaire émise à partir de la phase de rendu de l'interface utilisateur est exécutée en mode de validation automatique. L'auto-validation met la pression sur le serveur de base de données car chaque instruction doit vider le journal des transactions sur le disque, ce qui entraîne un trafic d'E / S important côté base de données. Une optimisation serait de marquer le
Connection
comme étant en lecture seule, ce qui permettrait au serveur de base de données d'éviter d'écrire dans le journal des transactions.Il n'y a plus de séparation des préoccupations car les instructions sont générées à la fois par la couche de service et par le processus de rendu de l'interface utilisateur. L'écriture de tests d'intégration affirmant le nombre d'instructions générées nécessite de passer par toutes les couches (web, service, DAO) tout en déployant l'application sur un conteneur web. Même lors de l'utilisation d'une base de données en mémoire (par exemple HSQLDB) et d'un serveur Web léger (par exemple Jetty), ces tests d'intégration seront plus lents à exécuter que si les couches étaient séparées et que les tests d'intégration back-end utilisaient la base de données, tandis que le les tests d'intégration frontale se moquaient complètement de la couche de service.
La couche d'interface utilisateur est limitée à la navigation dans les associations qui peuvent, à leur tour, déclencher des problèmes de requête N + 1 . Bien qu'Hibernate propose
@BatchSize
de récupérer des associations par lots etFetchMode.SUBSELECT
de faire face à ce scénario, les annotations affectent le plan de récupération par défaut, elles sont donc appliquées à chaque cas d'utilisation métier. Pour cette raison, une requête de couche d'accès aux données est beaucoup plus appropriée car elle peut être adaptée aux exigences de récupération de données du cas d'utilisation actuel.Enfin, la connexion à la base de données est maintenue tout au long de la phase de rendu de l'interface utilisateur, ce qui augmente la durée du bail de connexion et limite le débit global des transactions en raison de la congestion du pool de connexions à la base de données. Plus la connexion est maintenue, plus d'autres requêtes simultanées vont attendre pour obtenir une connexion à partir du pool.
Spring Boot et OSIV
Malheureusement, OSIV (Open Session in View) est activé par défaut dans Spring Boot , et OSIV est vraiment une mauvaise idée du point de vue des performances et de l'évolutivité .
Donc, assurez-vous que dans le
application.properties
fichier de configuration, vous avez l'entrée suivante:Cela désactivera OSIV afin que vous puissiez gérer
LazyInitializationException
la bonne manière .À partir de la version 2.0, Spring Boot émet un avertissement lorsque OSIV est activé par défaut, afin que vous puissiez découvrir ce problème bien avant qu'il n'affecte un système de production.
Pour plus de détails sur OSIV, consultez cet article .
la source