1. Mappage d'héritage
L'héritage est une caractéristique importante orientée objet. Il met en œuvre l'utilisation du code et a également une relation d'héritage dans le modèle de relation. Cette relation d'héritage peut en fait être considérée comme une relation d'énumération. De nombreux sous-types peuvent être énumérés dans un type. Ces sous-types forment une relation d'héritage avec l'objet parent. La plupart des énumérations pouvant être énumérées peuvent être considérées comme une carte d'héritage. Par conséquent, cette relation d'énumération peut être considérée comme une carte d'héritage. Par exemple, les animaux sont une classe abstraite, qui est la classe parentale d'autres animaux, porcs, chats, etc., et ils sont une relation d'héritage, comme le montre la figure ci-dessous:
Cette cartographie de l'héritage générera une table après sa transformation en modèle relationnel. Alors, comment ce tableau distingue-t-il ces deux types? Utilisez des champs relationnels, vous devez ajouter des champs de type à la table et utiliser des mots clés pour indiquer le type de l'objet. Par conséquent, la structure du tableau correspondant au modèle d'objet dans la figure ci-dessus est la suivante:
Lors de la génération de la structure du tableau, vous devez ajouter le type de champ correspondant, vous devez donc ajouter le discriminateur de carte correspondant au fichier de mappage. Ici, vous devez utiliser l'attribut discriminateur-valeur.
1. Fichiers de classe
Il n'est pas nécessaire de faire attention aux fichiers de classe, faites simplement attention à la relation d'héritage entre eux lors de l'écriture.
Listing: code de classe animale, il vous suffit d'ajouter des propriétés de base.
package com.src.hibernate; classe publique Animal {// numéro d'identification privé int id; public int getID () {return id; } public void setid (int id) {this.id = id; } // Nom du nom de chaîne privée; public String getName () {Nom de retour; } public void setName (string name) {this.name = name; } // Sexe booléen privé de genre; public booléen issex () {return sexe; } public void SetSex (Boolean Sex) {this.sex = sexe; }}Listing 2: Classes d'oiseaux et de porcs, ajouter des propriétés de base et hériter des classes d'animaux.
package com.src.hibernate; La classe publique Bird étend l'animal {// hauteur privée int hauteur; public int getheight () {return height; } public void Setheight (int height) {this.height = height; }} package com.src.hibernate; La classe publique Pig étend l'animal {// poids privé int poids; public int getweight () {return poids; } public void setweight (int Weight) {this.weight = poids; }} 2. Fichiers cartographiques
Le mappage correspondant doit être ajouté au fichier de mappage. Un seul fichier de mappage doit être ajouté au modèle, car un seul tableau est généré, le mappage de sous-classe correspondant est ajouté au fichier de mappage. Utilisez la balise <Sblass> et la valeur discriminatrice est ajoutée à la balise. Cette propriété discriminatrice indique quel type est écrit lors de l'écriture de données dans la base de données, comme suit:
<? xml version = "1.0"?> <! Doctype Hibernate-Mapping Public "- // Hibernate / Hibernate Mapping Dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <Hibernate-Mapping> <CLASSE NAME = "com.src.hiber.anim.anim.animon" table = "t_animal"> <id name = "id"> <générateur // id> <! - Ajoutez une balise d'authentification et doit être placée après l'ID -> <discriminator column = "type" /> <propriété name = "name" /> <propriété name = "sex" type = "booléen" /> <sous-classe name = "COM.SRC.Hibernate.pig" Discriminat name = "poids" /> </ subclass> <subclass name = "com.src.hibernate.bird" Discriminator-Value = "b"> <propriété name = "height" /> </ subclass> </ class> </ hibernate-mapping>
3. Résultats de l'analyse
La table de base de données MySQL générée ajoutera non seulement les attributs de base de l'animal, mais ajoutera également les propriétés du porc et de l'oiseau. Étant donné que les attributs ajoutés sont écrits à l'aide de <Sblass> dans le fichier de mappage, et les attributs de discriminator correspondants sont également ajoutés, de sorte que les colonnes de discriminatrice correspondantes seront ajoutées à la base de données. La structure de table générée est la suivante:
2. Fonctionnement des données
1. Écrivez des données
Lorsque vous effectuez des opérations de lecture et d'écriture de données, vous devez faire attention à l'utilisation des opérations dans la classe.
public void testsave () {session session = null; essayez {// créer une session de session Session = hibernateUtils.getSession (); // Open Transaction Session.beginTransaction (); Cochon de cochon = nouveau cochon (); pig.setname ("petit cochon"); pig.setsex (true); Pig.Setweight (200); Session.Save (Pig); Oiseau oiseau = nouvel oiseau (); Bird.setName ("Xiaoniao"); Bird.setSex (true); Bird.Seight (100); Session.Save (oiseau); session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}2. Query-Get et HQL polymorphes
La méthode de requête de base ne nécessite que l'utilisation de méthodes de chargement et d'obtention. Ici, nous nous concentrons sur la requête polymorphe. La requête polymorphe signifie que Hibernate peut utiliser l'instance de OFF pour identifier son véritable type d'objet lors du chargement d'un objet, afin qu'il puisse être une requête polymorphe.
Remarque: les requêtes polymorphes ne prennent pas en charge le chargement paresseux, c'est-à-dire que si vous utilisez la méthode de chargement, vous devez définir le chargement paresseux sur false dans le fichier de mappage.
3. Chargement de retard de charge
La charge prend en charge le chargement paresseux. Lors du chargement des objets, il génère en fait le proxy de l'objet. Par conséquent, lorsque vous utilisez des requêtes polymorphes, vous devez définir le chargement paresseux sur false dans le fichier de mappage, comme suit:
<? xml version = "1.0"?> <! Doctype Hibernate-Mapping Public "- // Hibernate / Hibernate Mapping Dtd 3.0 // en" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"> <Hibernate-Mapping> <CLASSE NAME = "com.src.hiber.anim.anim.animon" table = "t_animal" lazy = "false"> <id name = "id"> <générateur // id> <! - Ajoutez une balise d'authentification et doit être placé après l'ID -> <discriminator colonnen = "type" /> <propriété name = "name" /> <propriété name = "sexe" type = "boolean" /> <subclass name = "com.srcc.hibernate.pig" discriminator-valie = "p"> <propriété name = "poids" /> </ subclass> <subclass name = "com.src.hibernate.bird" Discriminator-Value = "b"> <propriété name = "height" /> </ subclass> </ class> </ hibernate-mapping>
Méthode de chargement de chargement, en utilisant la charge pour charger, cet exemple prend en charge les requêtes polymorphes et définir le chargement retardé sur false dans le fichier de configuration, afin que la méthode de chargement puisse être utilisée ici pour charger et obtenir la classe d'objets correspondante.
public void testload () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); Animal Ani = (Animal) Session.load (Animal.class, 1); System.out.println (ani.getName ()); // Parce que la charge prend en charge paresseux par défaut, nous voyons le proxy d'Animal // donc l'instance ne peut pas identifier le type de type vrai // la charge ne prend donc pas en charge la requête polymorphe dans ce cas if (ani instanceof pig) {System.out.println ("Je suis un cochon!"); } else {System.out.println ("Je ne suis pas un cochon!"); } session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }} 4.HQL Requête
HQL prend en charge les requêtes polymorphes, ce qui est principalement parce que la requête est un objet réel et ne renvoie pas de proxy. Par conséquent, HQL prend en charge les requêtes polymorphes. De plus, lors de l'interrogation, vous devez faire attention à ne pas utiliser de noms de table dans l'instruction de requête, mais à l'aide de noms de classe. Hibernate le mappera au nom de la table correspondant en fonction du nom de classe, comme suit:
public void testload5 () {session session = null; essayez {session = hibernateutils.getSession (); session.begintransaction (); List <Animal> list = session.CreateeQuey ("From Animal"). List (); for (iterator iter = list.iterator (); iter.hasnext ();) {animal a = (animal) iter.next (); if (a instanceof pig) {System.out.println ("Je suis un cochon!"); } else {System.out.println ("Je ne suis pas un cochon!"); }} session.getTransaction (). commit (); } catch (exception e) {e.printStackTrace (); session.getTransaction (). Rollback (); } enfin {hibernateUtils.closeSession (session); }}Résultats de la requête:
Hibernate: Sélectionnez Animal0_.id comme id0_, animal0_.name as name0_, animal0_.sex as sex0_, animal0_.weight as Weight0_, animal0_.height as height0_, animal0_.type as type0_ from t_animal animal0_ je suis un cochon! Je ne suis pas un cochon! Je suis un porcelet! Je ne suis pas un cochon!
3. Trois stratégies de cartographie des successions
1. Tableau par hiérarchie de classe
Supposons que nous ayons le paiement d'interface et ses plusieurs classes de mise en œuvre: CreditCardPayment, cashPayment et Chequepayment. Ensuite, le code de mappage de "Table par hiérarchie de classe" est le suivant:
<class name = "Payment" table = "PAYS"> <id name = "id" type = "long" column = "PAYS_ID"> <Generator /> </ id> <discriminator column = "PAYS_TYPE" type = "string" /> <propriété name = "Mult" Column = "Montr name = "CreditCardType" Column = "CCTYPE" /> ... </ Subclass> <sous-class name = "CashPayment" Discriminator-Value = "Cash"> ... </ Subclass> <Subclass Name = "Chequepayment" Discriminator-Value = "Check"> ... </sublass> </cassa>
Un seul tableau est nécessaire pour adopter cette stratégie. Il a une grande limitation: il nécessite que les champs définis par des sous-classes, tels que CCTYPE, ne puissent pas avoir de contraintes non nulles.
2. Un tableau par sous-classe
Pour les classes dans l'exemple ci-dessus, la stratégie de cartographie de "une table par sous-classe" est adoptée, et le code est le suivant:
<class name = "Payment" table = "PAYS"> <id name = "id" type = "long" chronn = "PAYS_ID"> <Generator /> </ id> <propriété name = "montant" chronn = "montant" /> ... <joint-subclass name = "CreditCardpayment" Table = Credit_payment "> <key column =" PAYS_ID "/> ... </ joined-subclass> name = "cashPayment" table = "cash_payment"> <key chronn = "Payment_id" /> <propriété name = "CreditCardType" Column = "CCTYPE" /> ... </ join-subclass> <join-suubclass name = "chequepayment" Table = "cheque_payment"> <key column = "PAYS_ID" /> ...
Quatre tables sont nécessaires. Les trois tables de sous-classe sont associées à la table de superclasse à travers les clés primaires (donc le modèle de relation est en fait une association individuelle).
3. Chaque sous-classe a une table (tableau par sous-classe) et utilisez le discriminateur
Notez que pour la stratégie de mappage de "une table par sous-classe", la mise en œuvre d'hibernate ne nécessite pas de champs de discriminatrice, tandis que d'autres outils de mappage d'objets / relationnels utilisent une méthode d'implémentation différente de Hibernate, qui nécessite une colonne de discriminatrice de type dans la table superclasse. La méthode adoptée par Hibernate est plus difficile à mettre en œuvre, mais du point de vue des relations (bases de données), elle est plus correcte. Si vous êtes prêt à utiliser la stratégie "Table par sous-classe" avec les champs de discernement, vous pouvez utiliser <Sblass> avec <join> comme suit:
<class name = "Payment" table = "PAYS"> <id name = "id" type = "long" chronn = "PAYS_ID"> <Generator /> </ id> <discriminator column = "Payment_Type" type = "String" /> <propriété Name = "Mult" Column = "Montant" /> ... <CRID-CLASS table = "Credit_Payment"> <propriété name = "CreditCardType" Column = "CCTYPE" /> ... </ join> </blass> <sous-classe Name = "CashPayment" Discriminator-Value = "Cash"> <Join Table = "Cash_Payment"> ... </woin> </sublass> </ Subclass Name = "Chequepayment" discriminator-value = "check"> <join table = "cheque_payment" fetch = "select"> ... </ joind> </ subclass> </ class> </ class>
La déclaration facultative fetch = "SELECT" est utilisée pour indiquer Hibernate que lors de l'interrogation des superclasses, n'utilisez pas de jointure externe pour saisir les données de la sous-classe Chequepayment.