Hibernate: asignaciones de componentes

UN ComponentEl mapeo es un mapeo para una clase que tiene una referencia a otra clase como variable miembro. Hemos visto tal mapeo mientras teníamos dos tablas y usamos el elemento <set> en el archivo de mapeo. Ahora usaremos el elemento <component> en el archivo de mapeo y se usaría una sola tabla para mantener los atributos contenidos dentro de la variable de clase.

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 tendrá una dirección, así que agreguemos campos específicos de dirección en la misma tabla de la siguiente manera:

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,
   street_name VARCHAR(40) default NULL,
   city_name   VARCHAR(40) default NULL,
   state_name  VARCHAR(40) default NULL,
   zipcode     VARCHAR(10) default NULL,
   PRIMARY KEY (id)
);

Definir clases POJO

Implementemos nuestra clase POJO Employee, que se utilizará para conservar los objetos relacionados con la tabla EMPLEADO.

import java.util.*;

public class Employee implements java.io.Serializable {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;
   private Address address;

   public Employee() {}
   
   public Employee(String fname, String lname, int salary, Address address ) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
      this.address = address;
   }
   
   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 Address getAddress() {
      return address;
   }
   
   public void setAddress( Address address ) {
      this.address = address;
   }
}

Necesitamos definir otra clase POJO correspondiente a la entidad ADDRESS que tiene campos relacionados con la dirección.

import java.util.*;

public class Address{
   private int id;
   private String street;     
   private String city;     
   private String state;    
   private String zipcode; 

   public Address() {}
   
   public Address(String street, String city, String state, String zipcode) {
      this.street = street; 
      this.city = city; 
      this.state = state; 
      this.zipcode = zipcode; 
   }
   
   public int getId() {
      return id;
   }
   
   public void setId( int id ) {
      this.id = id;
   }
   
   public String getStreet() {
      return street;
   }
   
   public void setStreet( String street ) {
      this.street = street;
   }
   
   public String getCity() {
      return city;
   }
   
   public void setCity( String city ) {
      this.city = city;
   }
   
   public String getState() {
      return state;
   }
   
   public void setState( String state ) {
      this.state = state;
   }
   
   public String getZipcode() {
      return zipcode;
   }
   
   public void setZipcode( String zipcode ) {
      this.zipcode = zipcode;
   }
   
}

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 <component> se utilizará para definir la regla para todos los campos asociados con la tabla ADDRESS.

<?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>
      
      <component name = "address" class="Address">
         <property name = "street" column = "street_name" type = "string"/>
         <property name = "city" column = "city_name" type = "string"/>
         <property name = "state" column = "state_name" type = "string"/>
         <property name = "zipcode" column = "zipcode" type = "string"/>
      </component>
      
      <property name = "firstName" column = "first_name" type = "string"/>
      <property name = "lastName" column = "last_name" type = "string"/>
      <property name = "salary" column = "salary" type = "int"/>
      
   </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 <component> El elemento establece la existencia de diferentes atributos de la clase Dirección dentro de las clases Empleado.

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 one address object */
      Address address1 = ME.addAddress("Kondapur","Hyderabad","AP","532");

      /* Add employee records in the database */
      Integer empID1 = ME.addEmployee("Manoj", "Kumar", 4000, address1);

      /* Let us have another address object */
      Address address2 = ME.addAddress("Saharanpur","Ambehta","UP","111");
  
      /* Add another employee record in the database */
      Integer empID2 = ME.addEmployee("Dilip", "Kumar", 3000, address2);

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

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

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

   }

   /* Method to add an address record in the database */
   public Address addAddress(String street, String city, String state, String zipcode) {
      Session session = factory.openSession();
      Transaction tx = null;
      Integer addressID = null;
      Address address = null;
      
      try {
         tx = session.beginTransaction();
         address = new Address(street, city, state, zipcode);
         addressID = (Integer) session.save(address); 
         tx.commit();
      } catch (HibernateException e) {
         if (tx!=null) tx.rollback();
         e.printStackTrace(); 
      } finally {
         session.close(); 
      }
      return address;
   }

   /* Method to add an employee record in the database */
   public Integer addEmployee(String fname, String lname, int salary, Address address){
      Session session = factory.openSession();
      Transaction tx = null;
      Integer employeeID = null;
      
      try {
         tx = session.beginTransaction();
         Employee employee = new Employee(fname, lname, salary, address);
         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 iterator = employees.iterator(); iterator.hasNext();){
            Employee employee = (Employee) iterator.next(); 
            System.out.print("First Name: " + employee.getFirstName()); 
            System.out.print("  Last Name: " + employee.getLastName()); 
            System.out.println("  Salary: " + employee.getSalary());
            Address add = employee.getAddress();
            System.out.println("Address ");
            System.out.println("\tStreet: " +  add.getStreet());
            System.out.println("\tCity: " + add.getCity());
            System.out.println("\tState: " + add.getState());
            System.out.println("\tZipcode: " + add.getZipcode());
         }
         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(); 
      }
   }
}

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 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 los mismos registros de tiempo se crearían en la tabla EMPLOYEE.

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

First Name: Manoj  Last Name: Kumar  Salary: 4000
Address
        Street: Kondapur
        City: Hyderabad
        State: AP
        Zipcode: 532
First Name: Dilip  Last Name: Kumar  Salary: 3000
Address
        Street: Saharanpur
        City: Ambehta
        State: UP
        Zipcode: 111
First Name: Manoj  Last Name: Kumar  Salary: 5000
Address
        Street: Kondapur
        City: Hyderabad
        State: AP
        Zipcode: 532
First Name: Dilip  Last Name: Kumar  Salary: 3000
Address
        Street: Saharanpur
        City: Ambehta
        State: UP
        Zipcode: 111

Si comprueba su tabla EMPLEADO, debería tener los siguientes registros:

mysql> select id, first_name,salary, street_name, state_name from EMPLOYEE;
+----+------------+--------+-------------+------------+
| id | first_name | salary | street_name | state_name |
+----+------------+--------+-------------+------------+
|  1 | Manoj      |   5000 | Kondapur    | AP         |
|  2 | Dilip      |   3000 | Saharanpur  | UP         |
+----+------------+--------+-------------+------------+
2 rows in set (0.00 sec)

mysql>