Hibernate es un marco que proporciona una capa de abstracción, lo que significa que el programador no tiene que preocuparse por las implementaciones, hace las implementaciones por usted internamente, como escribir consultas para realizar operaciones CRUD , establecer una conexión con la base de datos, etc. marco Java ORM (mapeo relacional de objetos) de código abierto, no invasivo y liviano que se utiliza para desarrollar una lógica de persistencia que es independiente del software de la base de datos.
Hibernate es capaz de almacenar las propiedades heredadas de un objeto junto con sus nuevas propiedades en su base de datos cuando un objeto se guarda en la base de datos. En Hibernate, la herencia entre clases POJO se aplica cuando varias clases POJO de un módulo contienen algunas propiedades comunes.
Mapeo de herencia de Hibernate
La orientación a objetos puede modelar las relaciones «es un» y «tiene un» . El modelo relacional solo admite la relación «tiene un» entre dos entidades. Hibernate ayuda a mapear dichos objetos con tablas relacionales. Hay tres estrategias de mapeo de herencia definidas en Hibernate.
- Tabla por jerarquía
- Tabla por clase de hormigón
- Tabla por subclase
Tabla por clase concreta (usando anotaciones)
Table per Concrete Class es una de las estrategias de herencia en hibernate. Si queremos mantener cada objeto de herencia de clase concreta en tablas separadas de la base de datos, entonces podemos proceder con la tabla por estrategia de clase concreta.
En una estrategia de Tabla por Clase Concreta:
- Hibernate almacena cada objeto de clase derivado de la jerarquía en una tabla separada de la base de datos.
- Los datos que pertenecen a una clase principal se encuentran dispersos en varias tablas de subclases, que representan clases concretas.
- No se requiere el discriminador, por lo que podemos evitar las anotaciones relacionadas con el discriminador.
En esta estrategia, cada tabla de subclase tendrá los atributos específicos de la subclase y los atributos heredados de la clase principal.
Anotaciones importantes
Anotación 1: @Herencia
Esta anotación define la estrategia de herencia que se utilizará para una jerarquía de clase de entidad. Se especifica en la clase de entidad que es la raíz de la jerarquía de clases de entidad. Si no se especifica la anotación @Inheritance o si no se especifica herencia para una jerarquía de clase de entidad, se utiliza la estrategia de mapeo SINGLE_TABLE .
Sintaxis: @Herencia
@Entity @Table("name = students") @Inheritance(strategy = InheritanceType.SINGLE_TABLE) // Class public class Student { // Insert code here }
Anotación 2: @AttributeOverride
La anotación @AttributeOverride se usa para anular la asignación de una propiedad o campo básico (ya sea explícito o predeterminado) o una propiedad o campo de Id. Esta anotación se puede aplicar a una entidad que extiende una superclase mapeada o a un campo o propiedad incorporados para anular un mapeo básico definido por la superclase mapeada o la clase integrable. Si no se especifica la anotación, la columna se asigna igual que en la asignación original.
Sintaxis: @AttributeOverride
@Entity @Table(name="students") @AttributeOverrides({ @AttributeOverride(name="name", column=@Column(name="NAME")), @AttributeOverride(name="age", column=@Column(name="AGE")) }) // Class public class Student { // Insert code here }
Implementación de la clase Table Per Concrete (usando anotaciones)
En este ejemplo, crearemos tres clases de persistencia con Employee como clase principal y P_Employee y C_Employee como las dos subclases.
Tenemos 3 tablas Employee, P_Employee y C_Employee . El mapeo de la subclase repite las propiedades de la clase padre.
Creando una tabla de base de datos para persistir clases concretas:
CREATE TABLE `Employee` ( `Id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL DEFAULT '0', `age` BIGINT(3) NOT NULL DEFAULT '0', PRIMARY KEY (`id`) ) CREATE TABLE `P_Employee` ( `Id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL DEFAULT '0', `age` BIGINT(3) NOT NULL DEFAULT '0', `salary` BIGINT(11) NULL DEFAULT NULL, PRIMARY KEY (`id`) ) CREATE TABLE `C_Employee` ( `Id` BIGINT(20) NOT NULL AUTO_INCREMENT, `name` VARCHAR(50) NOT NULL DEFAULT '0', `age` BIGINT(3) NOT NULL DEFAULT '0', `hourlyrate` BIGINT(11) NULL DEFAULT NULL, `duration` BIGINT(11) NULL DEFAULT NULL, PRIMARY KEY (`id`) )
La estructura del proyecto (IntelliJ IDEA) es la siguiente:
Creación de las clases Employee, P_Employee y C_Employee para la jerarquía anterior:
Archivo: Empleado.java
Java
// Java Program to Demonstrate Implementation // of Employee Class package com.exploit.model; // Importing required classes import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Inheritance; import javax.persistence.InheritanceType; import javax.persistence.Table; // Class @Entity @Table(name = "Employee2") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) public class Employee { @Id @GeneratedValue(strategy = GenerationType.AUTO) @Column(name = "id") // Class data member private int id; @Column(name = "name") private String name; @Column(name = "age") private String age; // Getter and Setters public int getId() { return id; } public void setId(int id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } }
Archivo: P_Employee.java
Java
// Java Program to Demonstrate P_Employee Class package com.exploit.model; // Importing required classes import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; // Class @Entity @Table(name = "P_Employee") public class P_Employee extends Employee { // Class data member @Column(name = "salary") private double salary; // Getter and setters public double getSalary() { return salary; } public void setSalary(double salary) { // this keyword refers to current instance itself this.salary = salary; } }
Archivo: C_Employee.java
Java
// Java Program to Demonstrate Implementation // of C_Employee Class package com.exploit.model; // Importing required classes import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.Table; // Class @Entity @Table(name = "C_Employee") public class C_Employee extends Employee { // Class data memebers @Column(name = "hourlyRate") private double hourlyRate; @Column(name = "duration") private double duration; // getters and setters public double getHourlyRate() { return hourlyRate; } public void setHourlyRate(double hourlyRate) { // this keyword refers to current instance this.hourlyRate = hourlyRate; } public double getDuration() { return duration; } public void setDuration(double duration) { this.duration = duration; } }
Crear un archivo de configuración hibernate.cfg.xml y agregar las entradas de los recursos de mapeo:
XML
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd"> <hibernate-configuration> <session-factory> <!-- Database connection properties --> <property name="connection.driver_class">com.mysql.jdbc.Driver</property> <property name="connection.url">jdbc:mysql://localhost/exploitdb</property> <property name="connection.username">root</property> <property name="connection.password">toor</property> <!-- JDBC connection pool (using the built-in) --> <property name="connection.pool_size">100</property> <!-- SQL dialect --> <property name="dialect">org.hibernate.dialect.MySQLDialect</property> <!-- Disable the second-level cache --> <property name="cache.provider_class">org.hibernate.cache.internal.NoCacheProvider</property> <!-- Echo all executed SQL to stdout --> <property name="show_sql">true</property> <!-- Format the generated Sql --> <property name="format_sql">true</property> <!-- Dont Drop and re-create the database schema on startup,Just update it --> <property name="hbm2ddl.auto">update</property> <mapping class="com.exploit.model.Employee" /> <mapping class="com.exploit.model.C_Employee" /> <mapping class="com.exploit.model.P_Employee" /> </session-factory> </hibernate-configuration>
Las siguientes son las dependencias utilizadas en el archivo pom.xml :
XML
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.geeksforgeeks.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <groupId>TablePerConcreteClassAnnotation</groupId> <artifactId>TablePerConcreteClassAnnotation</artifactId> <version>0.0.1-SNAPSHOT</version> <packaging>jar</packaging> <name>TablePerConcreteClassAnnotation</name> <url>http://maven.apache.org</url> <properties> <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> </properties> <dependencies> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-core</artifactId> <version>5.2.6.Final</version> </dependency> <!-- https://mvnrepository.com/artifact/mysql/mysql-connector-java --> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>6.0.5</version> </dependency> <!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-annotations --> <dependency> <groupId>org.hibernate</groupId> <artifactId>hibernate-annotations</artifactId> <version>3.5.6-Final</version> </dependency> </dependencies> </project>
Creando la clase que almacena el objeto persistente
Archivo: Main.java
Java
// Java Program to Illustrate Application Class package com.exploit.db; // Importing required classes import com.exploit.model.C_Employee; import com.exploit.model.Employee; import com.exploit.model.P_Employee; import com.exploit.util.HibernateUtil; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.Transaction; // Main class public class Main { // Main driver method public static void main(String[] args) { // Getting session factory using Hibernate Util // class SessionFactory sessionFactory = HibernateUtil.getSessionFactory(); // Getting session from Sesson factory Session session = sessionFactory.openSession(); // Begin transaction Transaction transaction = session.beginTransaction(); // Creating Employee base class record Employee employee = new Employee(); employee.setName("KirikoChan"); employee.setAge(19); // Creating Permanent Employee subclass record P_Employee permanentEmployee = new P_Employee(); permanentEmployee.setName("Saili.H"); permanentEmployee.setAge(20); permanentEmployee.setSalary(30000); // Creating Contract Employee subclass record C_Employee contractEmployee = new C_Employee(); contractEmployee.setName("ChikkoRita"); contractEmployee.setAge(21); contractEmployee.setHourlyRate(2000); contractEmployee.setDuration(7.5); // Persisting all the employee records session.persist(employee); session.persist(permanentEmployee); session.persist(contractEmployee); // Commit the transaction and // closing the session transaction.commit(); session.close(); // Display message System.out.println( "Employee records successfully persisted."); } }
Producción:
Employee records successfully persisted.
La clase Main se utiliza para conservar las instancias de objetos Employee, P_Employee y C_Employee . Esta es la forma habitual de mapear Table Per Concrete Class usando Anotaciones.