Hibernate - Asignaciones de listas

UN Listes una colección de Java que almacena elementos en secuencia y permite elementos duplicados. El usuario de esta interfaz tiene un control preciso sobre en qué lugar de la lista se inserta cada elemento. El usuario puede acceder a los elementos por su índice de números enteros y buscar elementos en la lista. Más formalmente, las listas generalmente permiten pares de elementos e1 y e2 tales que e1.equals (e2), y generalmente permiten múltiples elementos nulos si permiten elementos nulos.

Una lista se asigna con un elemento <list> en la tabla de asignación y se inicializa con java.util.ArrayList.

Definir tablas RDBMS

Considere una situación en la que necesitamos almacenar nuestros registros de empleados en la tabla EMPLOYEE, que tendrá la siguiente estructura:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Además, suponga que cada empleado puede tener uno o más certificados asociados a él. Una asignación de colección de lista necesita una columna de índice en la tabla de colección. La columna de índice define la posición del elemento en la colección. Por lo tanto, almacenaremos la información relacionada con el certificado en una tabla separada que tiene la siguiente estructura:

create table CERTIFICATE (
   id INT NOT NULL auto_increment,
   certificate_name VARCHAR(30) default NULL,
   idx INT default NULL, 
   employee_id INT default NULL,
   PRIMARY KEY (id)
);

Habrá one-to-many relación entre los objetos EMPLEADO y CERTIFICADO.

Definir clases POJO

Implementemos una clase POJO Employee, que se utilizará para conservar los objetos relacionados con la tabla EMPLOYEE y tener una colección de certificados en List variable.

import java.util.*;

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;
   private List certificates;

   public Employee() {}
   
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getFirstName() {
      return firstName;
   }
   
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   
   public String getLastName() {
      return lastName;
   }
   
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   
   public int getSalary() {
      return salary;
   }
   
   public void setSalary( int salary ) {
      this.salary = salary;
   }

   public List getCertificates() {
      return certificates;
   }
   
   public void setCertificates( List certificates ) {
      this.certificates = certificates;
   }
}

Necesitamos definir otra clase POJO correspondiente a la tabla CERTIFICATE para que los objetos de certificado se puedan almacenar y recuperar en la tabla CERTIFICATE.

public class Certificate{
   private int id;
   private String name; 

   public Certificate() {}
   
   public Certificate(String name) {
      this.name = name;
   }
   
   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;
   }
}

Definir archivo de asignación de Hibernate

Desarrollemos nuestro archivo de mapeo, que le indica a Hibernate cómo mapear las clases definidas a las tablas de la base de datos. El elemento <list> se utilizará para definir la regla para la colección de listas utilizada. El índice de la lista es siempre de tipo entero y se asigna mediante el elemento <list-index>.

<?xml version = "1.0" encoding = "utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
"-//Hibernate/Hibernate Mapping DTD//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name = "Employee" table = "EMPLOYEE">
      
      <meta attribute = "class-description">
         This class contains the employee detail. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <list name = "certificates" cascade="all">
         <key column = "employee_id"/>
         <list-index column = "idx"/>
         <one-to-many class="Certificate"/>
      </list>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </class>

   <class name = "Certificate" table = "CERTIFICATE">
      
      <meta attribute = "class-description">
         This class contains the certificate records. 
      </meta>
      
      <id name = "id" type = "int" column = "id">
         <generator class="native"/>
      </id>
      
      <property name = "name" column = "certificate_name" type = "string"/>
      
   </class>

</hibernate-mapping>

Debe guardar el documento de asignación en un archivo con el formato <classname> .hbm.xml. Guardamos nuestro documento de mapeo en el archivo Employee.hbm.xml. Ya está familiarizado con la mayoría de los detalles del mapeo, pero veamos todos los elementos del archivo de mapeo una vez más:

  • El documento de mapeo es un documento XML que tiene <hibernate-mapping> como elemento raíz, que contiene dos elementos <class>> correspondientes a cada clase.

  • los <class>Los elementos se utilizan para definir asignaciones específicas de clases Java a las tablas de la base de datos. El nombre de la clase Java se especifica mediante elname El atributo del elemento de clase y el nombre de la tabla de la base de datos se especifica utilizando el table atributo.

  • los <meta> El elemento es un elemento opcional y se puede utilizar para crear la descripción de la clase.

  • los <id>El elemento asigna el atributo de ID único en la clase a la clave principal de la tabla de la base de datos. losname atributo del elemento id se refiere a la propiedad en la clase y el columnun atributo se refiere a la columna de la tabla de la base de datos. lostype El atributo contiene el tipo de mapeo de hibernación, estos tipos de mapeo se convertirán del tipo de datos Java a SQL.

  • los <generator>El elemento dentro del elemento id se utiliza para generar los valores de clave primaria automáticamente. losclass atributo del elemento generador se establece en native para dejar que hibernate retome identity, sequence o hilo algoritmo para crear la clave principal en función de las capacidades de la base de datos subyacente.

  • los <property>El elemento se utiliza para asignar una propiedad de clase Java a una columna en la tabla de la base de datos. losname atributo del elemento se refiere a la propiedad en la clase y el columnEl atributo se refiere a la columna de la tabla de la base de datos. lostype El atributo contiene el tipo de mapeo de hibernación, estos tipos de mapeo se convertirán del tipo de datos Java a SQL.

  • los <list>El elemento se utiliza para establecer la relación entre las clases Certificado y Empleado. Usamos elcascadeatributo en el elemento <list> para decirle a Hibernate que persista los objetos de Certificado al mismo tiempo que los objetos de Empleado. losname el atributo se establece en el definido Listvariable en la clase padre, en nuestro caso son certificados .

  • los <key> El elemento es la columna de la tabla CERTIFICADO que contiene la clave externa del objeto principal, es decir, la tabla EMPLEADO.

  • los <list-index>El elemento se usa para mantener la posición del elemento y el mapa con la columna de índice en la tabla de colección. El índice de la lista persistente comienza en cero. Puede cambiar esto, por ejemplo, con <list-index base = "1" ... /> en su mapeo.

  • los <one-to-many>El elemento indica que un objeto Empleado se relaciona con muchos objetos Certificado y, como tal, el objeto Certificado debe tener un padre Empleado asociado. Puedes usar cualquiera<one-to-one>, <many-to-one> o <many-to-many>elementos basados ​​en su requerimiento. Si cambiamos este ejemplo para usar una relación de muchos a muchos, necesitaríamos una tabla de asociación para mapear entre los objetos padre e hijo.

Crear clase de aplicación

Finalmente, crearemos nuestra clase de aplicación con el método main () para ejecutar la aplicación. Usaremos esta aplicación para guardar algunos registros de los empleados junto con sus certificados y luego aplicaremos operaciones CRUD en esos registros.

import java.util.*;
 
import org.hibernate.HibernateException; 
import org.hibernate.Session; 
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class ManageEmployee {
   private static SessionFactory factory; 
   public static void main(String[] args) {
      
      try {
         factory = new Configuration().configure().buildSessionFactory();
      } catch (Throwable ex) { 
         System.err.println("Failed to create sessionFactory object." + ex);
         throw new ExceptionInInitializerError(ex); 
      }
      
      ManageEmployee ME = new ManageEmployee();
      /* Let us have a set of certificates for the first employee  */
      ArrayList set1 = new ArrayList();
      set1.add(new Certificate("MCA"));
      set1.add(new Certificate("MBA"));
      set1.add(new Certificate("PMP"));
     
      /* Add employee records in the database */
      Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, set1);

      /* Another set of certificates for the second employee  */
      ArrayList set2 = new ArrayList();
      set2.add(new Certificate("BCA"));
      set2.add(new Certificate("BA"));

      /* Add another employee record in the database */
      Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, set2);

      /* List down all the employees */
      ME.listEmployees();

      /* Update employee's salary records */
      ME.updateEmployee(empID1, 5000);

      /* Delete an employee from the database */
      ME.deleteEmployee(empID2);

      /* List down all the employees */
      ME.listEmployees();

   }

   /* Method to add an employee record in the database */
   public Integer addEmployee(String fname, String lname, int salary, ArrayList cert){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary);
         employee.setCertificates(cert);
         employeeID = (Integer) session.save(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return employeeID;
   }

   /* Method to list all the employees detail */
   public void listEmployees( ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         List employees = session.createQuery("FROM Employee").list(); 
         for (Iterator iterator1 = employees.iterator(); iterator1.hasNext();){
            Employee employee = (Employee) iterator1.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary());
            List certificates = employee.getCertificates();
            for (Iterator iterator2 = certificates.iterator(); iterator2.hasNext();){
               Certificate certName = (Certificate) iterator2.next(); 
               System.out.println("Certificate: " + certName.getName()); 
            }
         }
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to update salary for an employee */
   public void updateEmployee(Integer EmployeeID, int salary ){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         employee.setSalary( salary );
         session.update(employee);
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
   
   /* Method to delete an employee from the records */
   public void deleteEmployee(Integer EmployeeID){
      Session session = factory.openSession();
      Transaction tx = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = (Employee)session.get(Employee.class, EmployeeID); 
         session.delete(employee); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
   }
}

Compilación y ejecución

Estos son los pasos para compilar y ejecutar la aplicación anterior. Asegúrese de haber configurado PATH y CLASSPATH correctamente antes de continuar con la compilación y ejecución.

  • Cree el archivo de configuración hibernate.cfg.xml como se explica en el capítulo de configuración.

  • Cree el archivo de mapeo Employee.hbm.xml como se muestra arriba.

  • Cree el archivo fuente Employee.java como se muestra arriba y compílelo.

  • Cree el archivo fuente Certificate.java como se muestra arriba y compílelo.

  • Cree el archivo fuente ManageEmployee.java como se muestra arriba y compílelo.

  • Ejecute el binario ManageEmployee para ejecutar el programa.

Obtendría el siguiente resultado en la pantalla, y al mismo tiempo se crearían registros en las tablas EMPLOYEE y CERTIFICATE. Como puede ver, los certificados se han clasificado en orden inverso. Puede probar cambiando su archivo de mapeo, simplemente configuresort="natural" y ejecute su programa y compare los resultados.

$java ManageEmployee
.......VARIOUS LOG MESSAGES WILL DISPLAY HERE........

First Name: Manoj  Last Name: Kumar  Salary: 4000
Certificate: MCA
Certificate: MBA
Certificate: PMP
First Name: Dilip  Last Name: Kumar  Salary: 3000
Certificate: BCA
Certificate: BA
First Name: Manoj  Last Name: Kumar  Salary: 5000
Certificate: MCA
Certificate: MBA
Certificate: PMP

Si revisa sus tablas EMPLEADO y CERTIFICADO, deben tener los siguientes registros:

mysql> select * from EMPLOYEE;
+----+------------+-----------+--------+
| id | first_name | last_name | salary |
+----+------------+-----------+--------+
| 51 | Manoj      | Kumar     |   5000 |
+----+------------+-----------+--------+
1 row in set (0.00 sec)

mysql> select * from CERTIFICATE;
+----+------------------+------+-------------+
| id | certificate_name | idx  | employee_id |
+----+------------------+------+-------------+
|  6 | MCA              |    0 |          51 |
|  7 | MBA              |    1 |          51 |
|  8 | PMP              |    2 |          51 |
+----+------------------+------+-------------+
3 rows in set (0.00 sec

mysql>

Alternativamente, puede asignar una matriz de Java en lugar de una lista. Un mapeo de matriz es virtualmente idéntico al ejemplo anterior, excepto con diferentes nombres de elemento y atributo (<array> y <array-index>). Sin embargo, por las razones explicadas anteriormente, las aplicaciones de Hibernate rara vez usan matrices.