Hibernate: tabla por clase concreta mediante anotación

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.

Jerarquía de Clases

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: 

Estructura del proyecto

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.

Publicación traducida automáticamente

Artículo escrito por kaalel y traducido por Barcelona Geeks. The original can be accessed here. Licence: CCBY-SA

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *