1. Mapeo de herencia
La herencia es una característica importante orientada a objetos. Implementa el uso del código y también tiene una relación de herencia en el modelo de relación. Esta relación de herencia puede considerarse como una relación de enumeración. Muchos subtipos pueden enumerarse en un tipo. Estos subtipos forman una relación de herencia con el objeto principal. La mayoría de las enumeraciones que pueden enumerarse pueden considerarse como un mapa de herencia. Por lo tanto, esta relación de enumeración puede considerarse como un mapa de herencia. Por ejemplo, los animales son una clase abstracta, que es la clase padre de otros animales, cerdos, gatos, etc., y son una relación de herencia, como se muestra en la figura a continuación:
Este mapeo de herencia generará una tabla después de que se convierta en un modelo relacional. Entonces, ¿cómo distingue esta tabla entre estos dos tipos? Use campos relacionales, debe agregar campos de tipo a la tabla y usar palabras clave para indicar el tipo de objeto. Por lo tanto, la estructura de la tabla correspondiente al modelo de objeto en la figura anterior es la siguiente:
Al generar la estructura de la tabla, debe agregar el tipo de campo correspondiente, por lo que debe agregar el discriminador de mapa correspondiente al archivo de asignación. Aquí debe utilizar el atributo de valor discriminador.
1. Archivos de clase
No hay necesidad de prestar atención en los archivos de clase, solo preste atención a la relación de herencia entre ellos al escribir.
Listado: código de clase animal, solo necesita agregar propiedades básicas.
paquete com.src.Hibernate; Public Class Animal {// Id Number Private int id; public int getId () {return id; } public void setid (int id) {this.id = id; } // nombre Nombre de cadena privada; public String getName () {nombre de retorno; } public void setName (nombre de cadena) {this.name = name; } // sexo booleano privado de género; public boolean issex () {return sex; } public void setsex (sexo booleano) {this.sex = sex; }}Listado 2: clases de pájaros y cerdos, agregue propiedades básicas y heredan clases de animales.
paquete com.src.Hibernate; Public Class Bird extiende animal {// altura privada int altura; public int getheight () {altura de retorno; } public void setheight (int altura) {this.height = altura; }} paquete com.src.Hibernate; El cerdo de clase pública extiende animal {// peso privado int peso; public int getweight () {return peso; } public void setweight (int weight) {this.weight = weight; }} 2. Archivos de mapa
La asignación correspondiente debe agregarse al archivo de mapeo. Solo se debe agregar un archivo de asignación al modelo, porque solo se genera una tabla, la asignación de subclase correspondiente se agrega al archivo de asignación. Use la etiqueta <Subclase> y el valor de discriminador se agrega a la etiqueta. Esta propiedad discriminadora indica qué tipo se escribe al escribir datos en la base de datos, de la siguiente manera:
<? xml versión = "1.0"?> < table = "t_animal"> <id name = "id"> <generador // id> <!-Agregue una etiqueta de autenticación y debe colocarse después de la id-> <Discriminator columna = "type"/> <propiedad name = "name"/> <Property name = "sex" type = "boolean"/> <subclass name = "com.src.hibernate.pig" discriminator-valator name = "Weight"/> </subclass> <subclass name = "com.src.hibernate.bird" discriminator-value = "b"> <propiedad name = "height"/> </subclass> </class> </hibernate-mapping>
3. Resultados de análisis
La tabla de base de datos MySQL generada no solo agregará los atributos básicos de animal, sino que también agregará las propiedades del cerdo y el pájaro. Debido a que los atributos agregados se escriben utilizando <Subclass> en el archivo de mapeo, y también se agregan los atributos discriminadores correspondientes, por lo que las columnas discriminador correspondientes se agregarán a la base de datos. La estructura de la tabla generada es la siguiente:
2. Operación de datos
1. Escribir datos
Al realizar operaciones de lectura y escritura de datos, debe prestar atención al uso de operaciones en la clase.
public void testSave () {session session = null; Pruebe {// cree session object session = hibernateUtils.getSession (); // Abrir transacción session.BeginTransaction (); Pig Pig = New Pig (); Pig.setName ("Piudad pequeña"); pig.setsex (verdadero); Pig. Peso (200); Session.save (cerdo); Pájaro pájaro = nuevo pájaro (); Bird.setName ("Xiaoniao"); bird.setSex (verdadero); Bird.setheight (100); Session.save (pájaro); session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}2. Polimórfica de consulta y HQL
El método de consulta básica solo requiere usar métodos de carga y obtención. Aquí nos centramos en la consulta polimórfica. La consulta polimórfica significa que Hibernate puede usar instancia para identificar su tipo de objeto verdadero al cargar un objeto, para que pueda ser una consulta polimórfica.
Nota: Las consultas polimórficas no admiten la carga perezosa, es decir, si usa el método de carga, debe establecer la carga perezosa en falso en el archivo de asignación.
3. Carga de retraso de carga
La carga es compatible con la carga perezosa. Al cargar objetos, en realidad genera el proxy del objeto. Por lo tanto, al usar consultas polimórficas, debe establecer la carga perezosa en falso en el archivo de mapeo, de la siguiente manera:
<? xml versión = "1.0"?> < table = "t_animal" lazy = "false"> <id name = "id"> <generador // id> <!-Agregue una etiqueta de autenticación y debe colocarse después de la id-> <Discriminator column = "type"/> <property name = "name"/> <propiedad = "sexo" type = "boolean"/> <subclass name = "com.src.hibernate.pig" discriminator-value = "P"> <Property Name = "Weight"/> </subclass> <subclass name = "com.src.hibernate.bird" discriminator-value = "b"> <Property name = "Height"/> </subclass> </class> </ HiBernate-Mapping>
Método de carga de carga, usando la carga para cargar, este ejemplo admite consultas polimórficas y establece la carga retrasada en falso en el archivo de configuración, por lo que el método de carga se puede usar aquí para cargar y obtener la clase de objeto correspondiente.
public void testLoad () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); Animal ani = (animal) sess.Load (animal.class, 1); System.out.println (ani.getName ()); // Debido a que la carga admite perezoso por defecto, vemos el proxy de Animal // por lo que instancia de no puede identificar el tipo de cerdo verdadero //, por lo que la carga no admite consulta polimórfica en este caso si (ani instanceof pig) {system.out.println ("¡Soy un cerdo!"); } else {System.out.println ("¡No soy un cerdo!"); } session.getTransaction (). Commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }} 4. Consulta HQL
HQL admite consultas polimórficas, que se debe principalmente a que la consulta es un objeto real y no devuelve un proxy. Por lo tanto, HQL admite consultas polimórficas. Además, al consultar, debe prestar atención a no usar nombres de tabla en la declaración de consulta, sino usar nombres de clase. Hibernate lo asignará al nombre de la tabla correspondiente de acuerdo con el nombre de la clase, como sigue:
public void testLoad5 () {session session = null; intente {session = hibernateUtils.getSession (); session.BeginTransaction (); List <imeny> list = session.createQuery ("From Animal"). List (); for (iterator iter = list.iterator (); iter.hasnext ();) {animal a = (animal) iter.next (); if (una instancia de cerdo) {system.out.println ("¡Soy un cerdo!"); } else {System.out.println ("¡No soy un cerdo!"); }} session.getTransaction (). commit (); } catch (Exception e) {E.PrintStackTrace (); session.getTransaction (). Rollback (); } finalmente {hibernateUtils.clossessession (sesión); }}Resultados de la consulta:
Hibernate: Seleccione Animal0_.id como ID0_, animal0_.name as name0_, animal0_.sex as sex0_, animal0_.weight como weight0_, animal0_.Height as thight0_, animal0_.type como type0_ de t_animal animal0_ ¡soy un piglito! ¡No soy un cerdo! ¡Soy un lechón! ¡No soy un cerdo!
3. Tres estrategias para el mapeo de herencia
1. Tabla por jerarquía de clase
Supongamos que tenemos el pago de la interfaz y sus varias clases de implementación: CreditCardPayment, CashPayment y ChequePayment. Luego, el código de mapeo de "Tabla por jerarquía de clase" es el siguiente:
<class name = "PAYO" TABLE = "PAYO"> <id name = "id" type = "long" column = "paymay_id"> <generador/> </id> <discriminator column = "pagando_type" type = "string"/> <Property name = "cantidad" columna = "monta"/> ... <subclass name = "CreditCardPayment-Value-value =" Credit "CROUNTION" <CRODIL "<CONTISTA"/"Credittype namePePeMePe" Creditype "namepe" "Credit"> "Nombre de propiedad"> "Creditype" "Creditype" "Creditte"> "Creditte". columna = "cctype"/> ... </subclass> <subclass name = "cashPayment" discriminator-value = "efectivo"> ... </sublass> <subclass name = "chequepayment" discriminator-value = "check"> ... </subclass> </class>
Solo se necesita una tabla para adoptar esta estrategia. Tiene una gran limitación: requiere que los campos definidos por subclases, como CCType, no puedan tener restricciones no nulas.
2. Una mesa por subclase
Para las clases en el ejemplo anterior, se adopta la estrategia de mapeo de "una tabla por subclase", y el código es el siguiente:
<class name = "PAYO" TABLE = "PAYO"> <id name = "id" type = "long" column = "paymay_id"> <generador/> </id> <propiedad name = "monta" columna = "monto"/> ... <unión-subclass name = "creditCardPayment" table = "cred_payment"> <Key column = "PAYOT_ID"/> ... </JUNINE-SUBCLASS> <NEnEnEndEnsEn. name = "CashPayment" table = "Cash_payment"> <key column = "paymay_id"/> <Property name = "creditCardType" column = "cctype"/> ... </unión-subclass> <unir-subclass name = "chequepayment" table = "cheque_payment"> <key column = "pagando"/> ... </juseing-subcLass>
Se requieren cuatro tablas. Las tres tablas de subclase están asociadas con la tabla de superclase a través de claves primarias (por lo que el modelo de relación es en realidad una asociación uno a uno).
3. Cada subclase tiene una tabla (tabla por subclase) y usa el discriminador
Tenga en cuenta que para la estrategia de mapeo de "una tabla por subclase", la implementación de Hibernate no requiere campos discriminadores, mientras que otras herramientas de mapeo de objetos/relacionales usan un método de implementación diferente de Hibernate, que requiere una columna de discriminador de tipo en la tabla de superclase. El método adoptado por Hibernate es más difícil de implementar, pero desde la perspectiva de las relaciones (bases de datos), es más correcto. Si está dispuesto a usar la estrategia de "una tabla por subclase" con campos de discernimiento, puede usar <Subclass> con <Ance> como sigue:
<class name = "PAYO" TABLE = "PAYO"> <id name = "id" type = "long" column = "paymay_id"> <generador/> </id> <discriminator column = "paycte_type" type = "string"/> <Property name = "monta" columna = "monta"/> ... <subclass name = "acreedCardPayment-value-value =" Credit "CROUNTION". <Property Name = "CreditCardType" column = "cctype"/> ... </book> </ScClass> <subclass name = "casshPayment" discriminator-value = "efectivo"> <boin table = "cash_payment"> ... </board> </subclassshass> <subclass name = "kequepayment" discriminator-value = "cheque" table = "Cheque_payment" fetch = "Select"> ... </ Join> </subclass> </class> </class>
La declaración opcional Fetch = "Select" se usa para decirle a Hibernate que al consultar superclase, no use una unión externa para obtener los datos del subclase Chequepayment.