Le cache de la session est stocké avec des graphiques d'objets interdépendants. Par défaut, lorsque Hibernate charge les objets clients de la base de données, tous les objets de commande associés sont chargés en même temps. Prendre des cours de client et de commande comme exemples, supposons que la clé étrangère Customer_ID du tableau des commandes est autorisée à être nul
La méthode Session的find() suivante est utilisée pour récupérer tous les objets clients dans la base de données:
List customerLists=session.find("from Customer as c");
Lors de l'exécution de la méthode find() ci-dessus, HiberNate interroge d'abord tous les enregistrements dans le tableau des clients, puis interrogera le tableau des commandes avec des relations de référence en fonction de l'ID de chaque enregistrement. HiberNate exécutera les instructions de sélection suivantes à tour de rôle:
Sélectionner * parmi les clients;
Sélectionnez * dans les commandes où client_id = 1;
Sélectionnez * dans les commandes où client_id = 2;
Sélectionnez * dans les commandes où client_id = 3;
Sélectionnez * dans les commandes où client_id = 4;
Grâce aux 5 instructions de sélection ci-dessus, Hibernate charge enfin 4 objets clients et 5 objets de commande, formant un graphique d'objet associé en mémoire.
HiberNate utilise la stratégie de recherche par défaut maintenant lors de la récupération des objets de commande associés au client. Il y a deux lacunes majeures dans cette stratégie de recherche:
(1) Le nombre d'instructions sélectionnées est trop grand et un accès fréquent à la base de données affectera les performances de récupération. Si vous devez interroger N objets client, alors N + 1 L'instruction de requête SELECT doit être exécutée. Ceci est le problème de requête N + 1 sélectionné classique. Cette stratégie de recherche n'utilise pas la fonction de requête de connexion de SQL. Par exemple, les instructions de sélection ci-dessus peuvent être complètement terminées par l'instruction 1 Select suivante:
Sélectionnez * parmi les clients
sur clients.id = commandes.Customer_id
L'instruction SELECT ci-dessus utilise la fonction de requête extérieure gauche de SQL, qui peut interroger tous les enregistrements de la table des clients et les enregistrements de la table des commandes de correspondance dans une instruction SELECT.
(2) Dans les situations où la logique d'application n'a besoin que d'accès aux objets clients mais pas aux objets de commande, le chargement des objets de commande n'est pas complètement nécessaire. Ces objets d'ordre inutiles gaspillent beaucoup d'espace mémoire.
Pour résoudre les problèmes ci-dessus, Hibernate fournit deux autres stratégies de recherche: une stratégie de recherche retardée et une stratégie de recherche de connexion à gauche urgente. La stratégie de récupération retardée peut éviter le chargement redondant des objets associés auxquels l'application n'a pas besoin d'accéder. La stratégie urgente de récupération de la connexion extérieure gauche utilise pleinement la fonction de requête de connexion externe de SQL et peut réduire le nombre d'instructions sélectionnées.
Les problèmes de performances doivent être pris en compte lors de l'accès aux bases de données. Après avoir établi la relation 1-à plusieurs, le problème légendaire N +1 se produira dans la requête.
1) 1 à beaucoup, sur 1 carré, n objets peuvent être trouvés, puis l'ensemble associé à n objets doit être retiré, de sorte que la requête SQL d'origine devient n +1
2) Beaucoup à 1. Si vous interrogez les objets M dans plusieurs parties, l'objet à 1 Parts correspondant à M objets sera retiré, et il deviendra également M + 1.
1) Lazy = true, hibernate3 a déjà fait défaut à Lazy = true; Lorsque Lazy = true, l'objet associé ne sera pas interrogé immédiatement. L'action de requête ne se produira que lorsque l'objet associé (accédant à ses attributs, champs non ID).
2) Cache de niveau 2. Lorsque l'objet est beaucoup moins mis à jour, supprimé et ajouté que les requêtes, l'application du cache de niveau 2 n'a pas peur des problèmes de N +1, car même si la première requête est lente, le coup de cache sera très rapide après.
Différentes solutions et différentes idées, mais la seconde se trouve à nouveau à utiliser N +1.
3) Bien sûr, vous pouvez également définir fetch=join(annotation : @ManyToOne() @Fetch(FetchMode.JOIN))
Ce qui précède concerne la brève discussion de cet article sur le numéro Hibernate N + 1, et j'espère que cela sera utile à tout le monde. Les amis intéressés peuvent continuer à se référer à d'autres sujets connexes sur ce site. S'il y a des lacunes, veuillez laisser un message pour le signaler. Merci vos amis pour votre soutien pour ce site!