1. Requête d'objet entité
La requête d'objet d'entité est la base de la requête HQL. En tant que langage de requête d'objet, il est différent de SQL pendant les opérations de requête. Le contenu de la chaîne de requête doit être remplacé par le nom de classe et le nom d'attribut de classe. Cette méthode de requête est relativement simple. Tant que vous avez des compétences SQL, il est très simple d'utiliser HQL. Cependant, certains problèmes doivent être prêts à prêter attention, c'est-à-dire que l'interrogation et l'obtention de données n'est pas l'objectif, et ce qui doit être pris en compte, c'est comment rédiger des déclarations de requête efficaces, qui est au centre de la discussion.
1.N + 1 Problème
(1) Quel est le problème N + 1
Quand j'ai entendu ce nom pour la première fois, j'ai peut-être des doutes. Je n'ai jamais entendu parler du problème N + 1 auparavant. Alors qu'est-ce que cela signifie? N + 1 fait référence à n données dans un tableau, donc lors de l'obtention de ces n données, la commande N + 1 SQL sera générée. Cette opération est appelée n + 1. Ici, 1 fait référence à la publication d'une déclaration qui recherche la liste des ID et fait référence à la publication de n instructions SQL basées sur ID pour charger des objets connexes. Ce type d'opération de requête est très inefficace et est souvent généré dans les itérateurs. C'est-à-dire que si nous convertissons directement les résultats de la requête en itérateurs, ce problème se produira, comme suit:
public void testQuery () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); / ** * Il y aura un problème N + 1. Le soi-disant N + 1 Worth consiste à émettre des instructions N + 1 SQL * * 1: publier une instruction qui interroge la liste d'ID * * N: Issue N SQL Instructions basées sur l'ID et chargez l'objet pertinent * / iterator iter = session.CreateEquery ("From Student"). Itetere (); while (iter.hasnext ()) {étudiant étudiant = (étudiant) iter.next (); System.out.println (Student.GetName ()); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}Le code de requête ci-dessus entraînera un problème N + 1, car la requête est renvoyée en tant qu'itérateur, de sorte qu'une instruction SQL sera publiée si elle n'est pas générée une fois. Cela dépend principalement du mécanisme de requête de l'itérateur, qui interroge les données du cache. Si les données n'existent pas dans le cache, les données seront d'abord converties en mémoire, de sorte qu'une instruction de requête SQL sera publiée pour le moment, de sorte qu'une instruction SQL sera générée chaque itération. Cette méthode d'écriture est en fait une erreur et peut être résolue à l'aide d'autres méthodes pour optimiser.
(2) Évitez le problème N + 1
Le problème de N + 1 se produit en raison de l'utilisation inappropriée de l'itération. Bien sûr, d'autres méthodes peuvent être utilisées pour éviter ce problème de N + 1. Voici une méthode de liste. La plus grande différence entre la liste et l'itération est que la liste met les données dans le cache, mais n'utilise pas le cache. Par défaut, la liste publiera les instructions SQL à chaque fois. Avant d'utiliser Isterate, vous pouvez utiliser la liste pour enregistrer les données dans la base de données, afin que l'itération puisse lire à partir du cache lors de l'accès aux données, en évitant l'occurrence de problèmes N + 1. Le code est le suivant:
public void testQuery () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); Lister les étudiants = session.CreateeQuey ("From Student"). List (); System.out.println ("----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- Ensuite, aucune requête SQL basée sur ID n'est émise, et les données dans le cache sont directement utilisées * * ITÉRÉE Si les données existent dans le cache, il peut améliorer les performances, sinon les problèmes N + 1 se produiront * / // Vous pouvez utiliser le AS Alias Iterator Iter = Session.CreatEight ("From Student"). System.out.println (Student.getName ());} Session.getTransaction (). }}L'exemple ci-dessus évite le problème N + 1, car après avoir effectué l'opération de liste, les données seront placées dans le cache de session (cache de premier niveau). Par conséquent, lors de l'utilisation d'Iserate, une instruction sera publiée pour interroger la liste d'ID, puis les données correspondantes seront chargées dans le cache en fonction de l'ID. S'il y a des données qui les correspondent dans le cache, la requête de l'instruction SQL basée sur l'ID ne sera plus émise et les données du cache seront directement utilisées. La méthode d'itération peut améliorer les performances si les données existent dans le cache, sinon des problèmes N + 1 se produiront.
2. Requête de navigation d'objet
La navigation de l'objet fait référence à l'obtention de données d'un autre objet en fonction de la navigation d'attribut de l'objet dans un objet. Cela peut simplifier les instructions de requête et optimiser les méthodes de requête. Si nous suivons nos idées habituelles, nous pouvons réécrire et écrire un objet d'une autre classe pour obtenir le fonctionnement d'un autre objet, qui est plus lourd pour comparer l'instruction de navigation de l'objet.
@SuppressWarnings ({"Unchecked", "RawTypes"}) public void testQuery1 () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); // Renvoie la liste des attributs de set de résultats, les types de types d'élément et d'attribut dans la classe d'entité sont la même liste Students = Session.CreateeQuery ("From Student s Where s.classes.name comme '% 2%'"). List (); for (iterator item = students.iterator (); ite.hasnext ();) {étudiant obj = (étudiant) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}L'instruction de requête dans l'exemple ci-dessus utilise la méthode de navigation des objets. L'instruction de requête est la requête d'information de l'objet étudiant, mais les attributs de l'objet à comparer proviennent de l'attribut de nom de l'objet Classes. À l'heure actuelle, l'utilisation de la méthode de requête de navigation d'objet améliorera considérablement l'efficacité de la requête et optimisera l'instruction de requête. S'il s'agissait d'une méthode de requête ordinaire, un grand nombre d'instructions de connexion peuvent être générées, ce qui est très compliqué.
2. Requête native SQL
La valeur de requête native consiste à utiliser des instructions SQL pour interroger et obtenir des données, plutôt que d'utiliser des instructions HQL. Sa méthode d'utilisation est en fait très simple, similaire à HQL. Il vous suffit d'utiliser la méthode CreateSQLQuery pour interroger. Il est en fait similaire à la méthode CreateQuery de HQL. Le code est le suivant:
public void testQEury () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); List list = session.cretesqlQuery ("SELECT * FROM T_STUDENT"). List (); for (iterator item = list.iterator (); ite.hasnext ();) {objet [] obj = (objet []) ite.next (); System.out.println (obj [0] + "," + obj [1]); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}Le code ci-dessus utilise la méthode createSQLQuery. La chaîne de requête dans la méthode est une instruction SQL. Il implémente la méthode de requête de chaîne sous-jacente. La différence est que HQL a une autre couche d'emballage et configure les options de dialecte correspondantes dans hibernate.cfg.xml pour terminer le mappage.
3. Requête de connexion
Les requêtes de connexion sont souvent utilisées dans SQL pour obtenir une collection d'objets multiples. Parmi eux, les plus couramment utilisés sont la jointure intérieure, la jointure de gauche, la jointure droite, etc., qui se réfèrent à la requête de jointure intérieure, à la requête de jointure extérieure gauche et à la requête de jointure extérieure droite. Le contenu qu'ils renvoient pendant la requête est le produit cartésien entre entités, le contenu de la requête et un contenu de la table de gauche, le contenu de la requête et un contenu de la table droite, et la fonction de requête est puissante. La méthode de requête de connexion de HQL et la requête de connexion de SQL sont les mêmes dans les résultats de la requête, mais il existe de légères différences dans les instructions de requête.
1. Connexion intérieure
La requête intrajoin de HQL peut être interrogée à l'aide de l'instruction de jointure intérieure ou de l'instruction de jointure, et l'ensemble de résultats obtenu est un produit cartésien. Semblable à la requête intra-connexion SQL, la requête de jointure de HQL est divisée en deux types: explicite et implicite. La requête affichée fait référence au mot clé de jointure dans la chaîne de requête. La requête implicite n'a pas besoin d'ajouter la jointure dans la chaîne.
// Inner Connection @SuppressWarnings ({"Unchecked", "RawTypes"}) public void testQuery () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); // Renvoie la liste des attributs du jeu de résultats, les types de types d'élément et d'attribut dans la classe d'entité sont la même liste students = session.CreateeQuery ("SELECT S.NAME, C.NAME FROM Student S Join S.Classes C"). List (); for (iterator item = students.iterator (); ite.hasnext ();) {objet [] obj = (objet []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}
2. Connexion externe
Les connexions externes sont divisées en connexion extérieure gauche et requête de connexion externe droite. Les méthodes de requête sont similaires, mais le résultat de la requête est différent. Ils sont les mêmes que la connexion externe de SQL dans les résultats de la requête. La différence est la méthode d'écriture. Le code spécifique est le suivant:
@SuppressWarnings ({"Unchecked", "RawTypes"}) public void testQuery () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); // Renvoie la liste des attributs du jeu de résultats, les types de types d'élément et d'attribut dans la classe d'entité sont la même liste Students = Session.CreateeQuery ("SELECT S.NAME, C.Name From Student S Left Join S.Classes C"). List (); for (iterator item = students.iterator (); ite.hasnext ();) {objet [] obj = (objet []) ite.next (); System.out.println (obj [0]); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}Le code ci-dessus utilise une instruction de requête extérieure gauche. La méthode de requête extérieure droite correspondante est similaire à la jointure extérieure gauche. Convertissez simplement à gauche à droite. Les données de requête sont enregistrées dans l'objet de liste et le contenu de requête peut être obtenu via la liste.
4. Requête de dénomination externe
La requête nommée externe fait référence à la rédaction d'instructions de requête dans un fichier de mappage et à l'utilisation de la balise <query> pour définir les instructions HQL dans le fichier de mappage. De cette façon, les instructions HQL définies peuvent réaliser la fonction de configuration de la fonction. S'il y a un problème, il suffit de modifier la configuration. Si vous souhaitez utiliser cette instruction SQL, vous pouvez utiliser la méthode session.getNameDquery () dans le programme pour obtenir la chaîne de requête HQL, comme indiqué dans l'exemple suivant.
1. Énoncé de requête externe
L'exemple suivant démontre l'application des instructions de requête externes, ajouter la balise <wery> au fichier de mappage, ajouter l'attribut de nom à la balise et ajouter la chaîne à <! [Cdata []]>, afin que la chaîne de requête correspondante puisse être obtenue dans le programme en fonction de l'attribut de nom de la requête.
<? xml version = "1.0"?> <! Doctype Hibernate-Mapping public "- // Hibernate / Hibernate Mapping Dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <Hernate-Mapping> <classe nom = "com.src.hibern table = "t_student"> <id name = "id"> <générateur // id> <propriété name = "name" /> <propriété name = "CreateTime"> </ propriété> <! - Ajoutez une nouvelle colonne de classes à l'étudiant d'un côté, et le nom de la colonne devrait être le même que la liste de classes.hbm.xml -> <gourmandise> "Classes" colonne <query name = "QueryStudent"> <! [CDATA [Sélectionnez S de Student s Where S.Id <? ]]>> </ query> </ Hibernate-Mapping>
La requête nommée externe met l'instruction de requête dans le fichier de mappage, il peut donc être considéré comme une chaîne de requête publique. Il s'agit de son avantage, afin que d'autres fichiers de programme puissent être obtenus et utilisés. De plus, il augmente la commodité de la modification en tant que chaîne publique.
2. Application du programme
Après avoir défini des instructions de requête externes, il est nécessaire de les utiliser dans le programme. HQL fournit la méthode GetNameQuery pour obtenir la chaîne d'instruction de requête externe. Un nom de curseur externe doit être ajouté à cette méthode. HQL interrogera le bloc d'instruction SQL correspondant basé sur le nom du curseur, comme suit:
// Query de dénomination externe @SuppressWarnings ({"Unchecked", "RawTypes"}) public void testQuery () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); Liste des étudiants = session.getNamedQuery ("QueryStudent"). SetParameter (0, 10) .list (); for (iterator item = s - students.ite.hasnext ();) {étudiant obj = (étudiant) ite.next (); System.out.println (obj.getName ()); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}