La dernière fois que nous avons appris à utiliser des critères pour effectuer des opérations connexes ensemble, mais comme les critères ne sont pas la méthode de requête officiellement recommandée par Hibernate, nous ne l'utilisons pas beaucoup. Jetons maintenant un coup d'œil au HQL officiellement recommandé et découvrons à quel point il est puissant ensemble.
Quelle est la différence entre HQL, ou instruction de requête Hibernate et SQL? La différence entre une lettre, haha.
Bien sûr, ce n'est pas le cas. La différence entre HQL et SQL réside dans les différentes idées. HQL utilise une direction axée sur l'objet pour interroger, tandis que SQL utilise une requête pour les tables de base de données bidimensionnelles. Ce qui est inclus ici est la différence d'idées. HQL est en fait SQL, et il est fabriqué par Hibernate pour convertir et générer SQL en interne.
1) Sans plus tarder, jetons un coup d'œil à son pouvoir.
de l'utilisateur
Ce code est très familier, car nous utilisons souvent des noms de table dans SQL, mais la différence ici est que l'utilisateur n'est pas le nom de la table ici, mais le nom de la classe d'entité, et Hibernate nous aide à cartographier.
Associez les instructions SQL, si nous voulons trouver un certain attribut et la limiter conditionnellement en fonction d'un certain attribut, nous pouvons obtenir une déclaration similaire:
Sélectionnez usr.name, usr.age de l'utilisateur où usr.age> 20 et usr.age <60
De cette façon, nous avons trouvé les noms et les âges des utilisateurs de plus de 20 ans et moins de 60 ans. C'est facile à comprendre.
Le et, ou, comme, <,>, = et ainsi de suite dans les instructions SQL peuvent tous être utilisés dans HQL.
Il convient de noter que lorsque nous interrogeons plusieurs attributs, le résultat renvoyé est un tableau d'objet [], et lorsqu'un seul, l'objet est renvoyé. Cela nécessite différentes méthodes d'analyse, vous devez donc y faire attention lors de l'interrogation.
2) Bien sûr, nous avons dit plus tôt que HQL était orienté objet, et si nous le faisons, ce n'est pas une idée orientée objet. Changeons-le:
Sélectionnez un nouvel utilisateur (usr.name, usr.age) de l'utilisateur USR où usr.age> 20De cette façon, nous mettons le résultat de la requête dans l'objet utilisateur. Notez que le constructeur utilisateur est appelé ici. Il doit y avoir un constructeur utilisateur qui reçoit deux paramètres dans la classe utilisateur, sinon une erreur sera signalée. Le message d'erreur est à peu près le suivant:
Impossible de localiser le constructeur approprié en classe [org.hibernate.tutorial.domain8.user]
Il ne peut pas trouver un constructeur approprié. Il est très clair que ajoutez simplement le constructeur qui reçoit les paramètres correspondants.
Notez que lorsque nous avons vérifié l'ID correspondant, nous ne l'avons pas découvert. Si nous appelons la méthode SaveorUpdate pour le moment, elle a effectivement effectué l'opération enregistrée.
Jetons un coup d'œil au code de test:
Après avoir exécuté l'instruction de requête ci-dessus, j'effectue les opérations suivantes:
while (iter.hasnext ()) {user user = (user) iter.next (); user.setName ("Sun2"); session.saveorupdate (utilisateur); } À l'heure actuelle, la déclaration Hibernate est:
Hibernate: Insérer dans les valeurs utilisateur (user_name, âge) (? ,?)
Il en insère un nouveau, pas une mise à jour.
Ensuite, si nous en avons besoin pour mettre à jour, nous devons découvrir l'ID ensemble:
Sélectionnez un nouvel utilisateur (usr.name, usr.age, usr.id) depuis l'utilisateur usr où usr.age> (sélectionnez avg (usr.age) depuis usr)
N'oubliez pas de modifier le constructeur utilisateur.
Pour le moment, nous exécutons à nouveau notre code de test et vous obtiendrez:
HiberNate: Mettez à jour le set utilisateur user_name =?, Age =? où user_id =?
Sélectionnez usr.name dans l'utilisateur USR où usr.age> (sélectionnez AVG (usr.age) dans USR)
Ce HQL détecte le nom de l'utilisateur plus âgé que l'âge moyen.
4) Dans Hibernate 3, nous pouvons facilement mettre à jour et supprimer des objets, sans avoir à charger d'abord, puis supprimer en 2. Nous pouvons le faire directement dans une instruction:
Mettre à jour le jeu d'utilisateurs Nom = '123123' où name = 'Sun33'
Les déclarations de suppression sont similaires:
Supprimer l'utilisateur où name = '123123'
5) Il est également facile de se regrouper et de trier en hibernate. Utilisez simplement un groupe par commande, et je n'en parlerai pas plus pour le moment.
6) Nous voyons que ce qui précède est écrit directement sur la requête ou la mise à jour. Si nous avons besoin d'une affectation dynamique, ou qu'il y a trop d'affectations, nous ne pouvons pas épisser des chaînes comme JDBC. On estime qu'il y en a plus de 5, et tout le monde dans l'équipe de projet veut me gronder, haha.
Il est préférable d'utiliser une méthode moderne, d'utiliser des espaces réservés à la place, puis de définir des valeurs spécifiques.
Notre code direct:
Query query = session.CreateeQuery ("Select New User (usr.name, usr.age, usr.id) de l'utilisateur usr où usr.name =?"); Query.SetString (0, "shun"); Nous voyons que cette méthode est similaire à celle que nous utilisons directement. Il est réglé à travers le jeu ***, mais la différence est que la position ici commence à partir de 0, tandis que le statement préparé commence à partir de 1, alors faites une attention particulière ici.
Il y a aussi une méthode de session.find dans HiberNate2, mais depuis que j'utilise 3 maintenant, je n'en dirai pas grand-chose.
L'ensemble d'espace que nous avons utilisé ci-dessus est appelé l'espace réservé de l'ordre, et il y en a un autre appelé l'espace réservé de référence. Jetons un coup d'œil:
Query Query = Session.CreateeQuery ("Select New User (usr.name, usr.age, usr.id) de l'utilisateur usr où usr.name =: name"); query.setParameter ("name", "shun"); J'ai vu qu'il y a une chose comme: nom dans notre déclaration HQL. Il s'agit d'un espace réservé de référence. Nous n'avons qu'à définir la valeur via SetParameter plus tard. Notez que le premier paramètre ici doit correspondre à la valeur d'espace réservé dans l'instruction HQL.
Bien sûr, certaines personnes peuvent dire que ce n'est pas axé sur les objets, alors allons à nouveau orienté objet:
Tout d'abord, créez une classe pour résumer la valeur que nous interrogeons
Classe publique UserViery {Nom de chaîne privée; Âge privé; // omettez la méthode get / set} query query = session.createequery ("sélectionner nouvel utilisateur (usr.name, usr.age, usr.id) de l'utilisateur usr où usr.name =: name"); UserQuery uq = new UserQuery (); uq.setName ("shun"); query.setProperties (UQ); Nous encapsulons les valeurs dont nous avons besoin pour interroger directement via cette classe. Très orienté objet.
Certaines équipes de projet ont des réglementations étranges selon lesquelles les instructions SQL ne sont pas autorisées à apparaître dans le code. S'il s'agit d'une spécification, tous les codes de notre entreprise que j'ai vus ne sont pas qualifiés. Beaucoup d'épissage de cordes dans la tasse le rend déprimé. Il est vraiment difficile d'être blessé de maintenir les projets existants.
Les instructions SQL ne sont pas autorisées dans le code. C'est une bonne suggestion, mais cela dépend de l'occasion. Jetons un coup d'œil à la façon dont Hibernate configure HQL dans les fichiers de mappage.
Regardez directement le fichier de configuration:
<query name = "queryByName"> <! [cdata [de l'utilisateur usr where usr.name =: name]]> </ query>
Nous avons ajouté une balise comme celle-ci, ce qui indique qu'il s'agit d'une instruction HQL.
Lorsque nous devons obtenir cette instruction, nous devons seulement ajouter une phrase au code:
Query query = session.getNameDquery ("queryByName"); De cette façon, l'instruction HQL est obtenue.
HQL peut également être interrogé à l'aide de combinaisons en SQL, telles que la jointure intérieure, la jointure extérieure gauche, la jointure extérieure droite, la jointure complète.
Jetons un coup d'œil à leur utilisation:
Jetons un coup d'œil à la classe d'entité en premier, ce que nous devons utiliser dans nos tests:
classe publique TUSER implémente Serializable {private statique final long SerialVersionUID = 1l; INT PRIVÉ ID; Âge privé; nom de chaîne privé; set privé <adress> adresses = new HashSet <Address> (); // OMIT Method Get / Set} L'adresse de classe publique implémente Serializable {private static final long SerialVersionUID = 1l; INT PRIVÉ ID; adresse de chaîne privée; Utilisateur de tus-pour-tuer privé; // omettre la méthode get / set} Jetons un coup d'œil au fichier de mappage:
<hibernate-mapp package = "org.hibernate.tutorial.domain6"> <class name = "tuser" table = "t_user" dynamic-insert = "id"> dynamic-update = "true"> <id name = "id" chronn = "id"> <générateur /> </ id> <propriété name = "name" type = "java.Lang.string" collun = "/ column <name" type = "java.Lang.String" name = "Age" type = "java.lang.integer" chronn = "age" /> <set name = "adresses" cascade = "all" table = "t_address" inverse = "true"> <key column = "user_id" /> <hibernate-mapping package = "org.hibernate.tutorial.domain6"> <class name = "adresse" table = "t_address" dynamic-insert = "false" dynamic-update = "false" dynamic-update = "false" dynamic-update = "id" type = "java.lan type = "java.lang.string" /> <plusieurs à un name = "user" chronn = "user_id" not-null = "true"> </suly-to-one> </ class> </ hibernate-mapping>
Il vous suffit de modifier le nom du package correspondant.
Effectuons des tests formels:
Avant les tests, regardons les données du tableau:
Les données de la table T_Address sont les suivantes:
Les données de la table T_User sont les suivantes:
1) Tout d'abord, jetons un coup d'œil à la jointure intérieure, qui est récupérée dans HQL par la jointure intérieure Fetch. Notez que la signification de récupérer ici est de récupérer les données requises. Si la récupération n'est pas utilisée, les données que nous avons récupérées sont du type de données de l'objet [].
Jetons un coup d'œil en premier
De TUSER USR INTER JOIN RETCH USR.ADRESSES
Lorsque nous l'exécutons, nous voyons que la sortie Hibernate est:
HiberNate: sélectionnez tuser0_.id as id1_0_, adresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as agent1_0_, adresses1_.address as adress0_1_, adresse t_address Adresses1_ sur tuser0_.id = adresses1_.user_id
Nous pouvons voir les résultats lors de l'exécution dans MySQL:
Nous pouvons voir que Hibernate le convertit en une déclaration de jointure intérieure et découvre l'adresse.
Nous voyons qu'il n'y a aucun enregistrement de Shun4 dans le résultat, car il n'a pas l'adresse et l'enregistrement correspondantes.
Lorsque nous utilisons la jointure intérieure au lieu de récupérer, l'instruction qu'il imprime est:
HiberNate: sélectionnez tuser0_.id as id1_0_, adresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as ge1_0_, adresses1_.address as adresse0_1_, adresse tuser0_.id = adresses1_.user_id
Il semble que la déclaration n'est pas différente, mais lorsque nous le découvrons, elle obtient un type de tableau d'objet [], vous devez donc faire attention à cette analyse.
Lorsque nous n'utilisons pas Fetch mais que nous joignons à l'intérieur, nous devons l'analyser comme ceci:
Query Query = Session.CreateeQuery ("De TUSER USR Inner Join USR.Address"); List list = query.list (); Iterator iter = list.iterator (); while (iter.hasnext ()) {object [] résultats = (objet []) iter.next (); for (int i = 0; i <result.Length; i ++) {System.out.println (résultats [i]); }} Nous voyons le résultat de l'impression:
org.hibernate.tutorial.domain6.tuser@16925b0 org.hibernate.tutorial.domain6.address@914f6a org.hibernate.tutorial.domain6.address@71dc3d org.hibernate.tutorial.domain6.tuser@1326484 org.hibernate.tutorial.domain6.address@16546ef
Chacun de ses résultats est l'objet correspondant.
2) Join extérieur gauche, cela équivaut à la connexion gauche de SQL. Jetons un coup d'œil directement à l'exemple:
De TUSER USR GAUT EXTERA
Lorsque nous exécutons l'instruction ci-dessus, Hibernate imprime:
Hibernate: select tuser0_.id as id1_0_, addresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as age1_0_, addresses1_.address as address0_1_, addresses1_.user_id as user3_0_1_, addresses1_.id as id0__ from t_user tuser0_ left outer rejoindre t_address adresses1_ sur tuser0_.id = adresses1_.user_id
Nous l'avons vérifié dans MySQL et vu:
Nous voyons que bien que Shun4 n'ait pas d'adresse correspondante, il est toujours découvert. La jointure extérieure gauche fait référence à la recherche de tous les enregistrements dans la table de gauche.
Je ne parlerai pas de la situation sans récupérer ici.
3) Ensuite, jetons un coup d'œil à la bonne jointure extérieure. À en juger par le nom, il doit être lié à la jointure extérieure gauche. Nous pouvons le voir clairement en regardant directement les exemples.
De TUSER USR droit extérieur jointure Fetch Usr.Address
Nous l'exécutons et obtenons la sortie de l'instruction de résultats de Hibernate est:
HiberNate: sélectionnez tuser0_.id as id1_0_, adresses1_.id as id0_1_, tuser0_.name as name1_0_, tuser0_.age as agent1_0_, adresses1_.address as adress0_1_, adresse rejoindre t_address adresses1_ sur tuser0_.id = adresses1_.user_idNous pouvons voir les résultats après l'exécution dans MySQL:
Ici, nous pouvons voir que l'adresse est TEST4 et ne dispose pas de l'utilisateur correspondant, mais il est toujours découvert. La jointure extérieure droite fait référence à la recherche de tous les enregistrements dans la bonne table.
La situation de récupération est comme ci-dessus. Si vous ne comprenez pas, vous pouvez jeter un œil à Inner Join Fetch.