Hibernate - Asignaciones de mapas

UN Mapes una colección de Java que almacena elementos en pares clave-valor y no permite elementos duplicados en la lista. La interfaz del mapa proporciona tres vistas de colección, que permiten ver el contenido de un mapa como un conjunto de claves, una colección de valores o un conjunto de asignaciones clave-valor.

Un mapa se mapea con un elemento <map> en la tabla de mapeo y se puede inicializar un mapa desordenado con java.util.HashMap.

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. 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_type VARCHAR(40) default NULL,
   certificate_name VARCHAR(30) 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 Map 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 Map getCertificates() {
      return certificates;
   }
   
   public void setCertificates( Map 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 <map> se utilizará para definir la regla para el mapa utilizado.

<?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>
      <map name = "certificates" cascade="all">
         <key column = "employee_id"/>
         <index column = "certificate_type" type = "string"/>
         <one-to-many class="Certificate"/>
      </map>
      <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 el 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 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 <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 <map>El elemento se utiliza para establecer la relación entre las clases Certificado y Empleado. Usamos elcascadeatributo en el elemento <map> 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 Mapvariable en la clase padre, en nuestro caso son certificados .

  • los <index>El elemento se utiliza para representar las partes clave del par de mapas clave / valor. La clave se almacenará en la columna certificate_type utilizando un tipo de cadena.

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

  • 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.

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 un registro de empleado junto con una lista de certificados y luego aplicaremos operaciones CRUD en ese registro.

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  */
      HashMap set = new HashMap();
      set.put("ComputerScience", new Certificate("MCA"));
      set.put("BusinessManagement", new Certificate("MBA"));
      set.put("ProjectManagement", new Certificate("PMP"));
     
      /* Add employee records in the database */
      Integer empID = ME.addEmployee("Manoj", "Kumar", 4000, set);

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

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

      /* 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, HashMap 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());
            Map ec = employee.getCertificates();
            System.out.println("Certificate: " + 
              (((Certificate)ec.get("ComputerScience")).getName()));
            System.out.println("Certificate: " + 
              (((Certificate)ec.get("BusinessManagement")).getName()));
            System.out.println("Certificate: " + 
              (((Certificate)ec.get("ProjectManagement")).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 mencionada anteriormente. 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.

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

First Name: Manoj  Last Name: Kumar  Salary: 4000
Certificate: MCA
Certificate: MBA
Certificate: PMP
First Name: Manoj  Last Name: Kumar  Salary: 5000
Certificate: MCA
Certificate: MBA
Certificate: PMP

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

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

mysql>select * from CERTIFICATE;
+----+--------------------+------------------+-------------+
| id | certificate_type   | certificate_name | employee_id |
+----+--------------------+------------------+-------------+
| 16 | ProjectManagement  | PMP              |          60 |
| 17 | BusinessManagement | MBA              |          60 |
| 18 | ComputerScience    | MCA              |          60 |
+----+--------------------+------------------+-------------+
3 rows in set (0.00 sec)

mysql>