Configuración de Hibernate mediante Fichero XML
Vamos a ver cuál es la forma de realizar la configuración clásica de Hibernate mediante un fichero XML. Para ello, usaremos un proyecto Maven al que habilitaremos Hibernate mediante las dependencias requeridas. Hay que tener en cuenta que la configuración mediante XML ya se encuentra en desuso y hoy en día se emplea la configuración mediante fichero Properties y mediante Annotated Class. Pero, como siempre digo, es conveniente saber cómo funciona la metodología XML ya que en nuestra vida laboral es posible que nos encontremos con muchos proyectos de cierta antigüedad que todavía sigan operando mediante dicha configuración.
👉 Antes de empezar, unos comentarios. Por si no lo sabéis, diremos que Hibernate es un framework que implementa la especificación JPA (Java Persistence API) y que se emplea en la parte del Backend. Hay que tener en cuenta que tanto Hibernate como JPA facilitan enormemente el desarrollo del software que se encarga de realizar el acceso a la Base de Datos, ya que automatiza parte del complejo proceso que había que implementar hace 20 años con la especificación JDBC (Java Data Base Connectivity). La librería JPA se importa como javax.persistence.* y el framework Hibernate se importa como org.hibernate.*. Por supuesto, aunque Hibernate cubre toda la librería JPA, hay que puntualizar que va más allá e incorpora funcionalidad adicional.
Configuración de Hibernate mediante Fichero XML
Pues nada, aclarado lo anterior, vamos a revisar los pasos necesarios para habilitar Hibernate en nuestro proyecto con la configuración XML. Serían los siguientes.
1º) Nos creamos un proyecto Maven normal. En mi caso establezco como paquete base el com.universo.fichero, pero vosotros podéis usar cualquier otro.
2º) Nos vamos al fichero pom.xml y añadimos las dependencias necesarias para descargarnos las librerías asociadas a Hibernate y MySql. El fichero pom.xml debería quedar algo así:
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.universo.fichero</groupId>
<artifactId>HibernateConfigXml</artifactId>
<version>0.0.1-SNAPSHOT</version>
<!-- Propiedades que van a ser usadas por las dependencias -->
<properties>
<hibernate.version>5.4.1.Final</hibernate.version>
</properties>
<dependencies>
<!-- Dependencias de Hibernate cuyas librerias deben ser descargadas -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-core</artifactId>
<version>${hibernate.version}</version>
</dependency>
<!-- Dependencias de Mysql - Driver JDBC -->
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>8.0.14</version>
<scope>runtime</scope>
</dependency>
</dependencies>
</project>
3º) Seleccionamos el proyecto y lanzamos la opción MAVEN - UPDATE PROJECT. De este modo, Eclipse se descargará las librerías necesarias para nuestro proyecto. Las Maven Dependencies deberían quedar de este modo.
👉 Como se aprecia, ahora nuestro proyecto tiene, entre otras, las siguientes librerías correspondientes a Hibernate, JPA y Mysql:
- hibernate-core-5.4.1.Final.jar
- hibernate-commons-annotations-5.1.0.Final.jar
- javax.persistence-api-2.2.jar
- mysql-connector-java-8.0.14.jar
4º) A continuación, nos creamos una tabla MySql para probar la conexión proporcionada por Hibernate. Por ejemplo, nos creamos la tabla "valor".
CREATE TABLE `universojava`.`valor` (
`id` INT(11) NOT NULL AUTO_INCREMENT,
`nombre` VARCHAR(45) NOT NULL,
`ticker` VARCHAR(10) NOT NULL,
`indice` VARCHAR(10) NULL,
`pais` VARCHAR(20) NULL,
`rentabilidad` FLOAT NULL,
PRIMARY KEY (`id`));
5º) Damos de alta algunos registros para que podamos operar con ellos y con eso damos por concluida la incursión en la parte de Base de Datos.
Creación de los componentes del proyecto
6º) Volvemos ahora a nuestro proyecto Eclipse y pasamos a crear el objeto entidad Valor.java que se va a emparejar con la tabla "valor" que acabamos de crearnos. Esta clase tenemos que definirla con las anotaciones @Entity y @Table.
En cuanto a los atributos de la misma, tenemos que marcarlos con la anotación @Column para asociarlos con la columna correspondiente de la tabla MySql. En cuanto a la Primary Key de la tabla, en nuestra entidad tendremos que marcarla con la anotación @Id.
💎 Hay que mencionar que todas las anotaciones anteriores pertenecen a la librería javax.persistence.* de la especificación JPA.
En definitiva, debería quedarnos algo similar a esto:
// **************************************************
package com.universo.fichero.modelo;
//Importar Anotaciones de JPA
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Table;
@Entity
@Table(name="valor")
public class Valor {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name="id")
private Long id;
@Column(name="nombre")
private String nombre;
@Column(name="ticker")
private String ticker;
@Column(name="indice")
private String indice;
@Column(name="pais")
private String pais;
@Column(name="rentabilidad")
private Float rentabilidad;
public Valor() {
super();
}
public Valor(String nombre, String ticker, String indice, String pais,
Float rentabilidad) {
super();
this.nombre = nombre;
this.ticker = ticker;
this.indice = indice;
this.pais = pais;
this.rentabilidad = rentabilidad;
}
public Valor(String nombre, String ticker, String indice, String pais,
Float rentabilidad) {
super();
this.nombre = nombre;
this.ticker = ticker;
this.indice = indice;
this.pais = pais;
this.rentabilidad = rentabilidad;
}
public Valor(Long id, String nombre, String ticker, String indice, String pais,
Float rentabilidad) {
super();
this.id = id;
this.nombre = nombre;
this.ticker = ticker;
this.indice = indice;
this.pais = pais;
this.rentabilidad = rentabilidad;
}
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getNombre() {
return nombre;
}
public void setNombre(String nombre) {
this.nombre = nombre;
}
public String getTicker() {
return ticker;
}
public void setTicker(String ticker) {
this.ticker = ticker;
}
public String getIndice() {
return indice;
}
public void setIndice(String indice) {
this.indice = indice;
}
public String getPais() {
return pais;
}
public void setPais(String pais) {
this.pais = pais;
}
public Float getRentabilidad() {
return rentabilidad;
}
public void setRentabilidad(Float rentabilidad) {
this.rentabilidad = rentabilidad;
}
@Override
public String toString() {
return "Valor [id=" + id + ", nombre=" + nombre + ", ticker=" + ticker +
", indice=" + indice + ", pais=" + pais +
", rentabilidad=" + rentabilidad + "]";
}
}
// **************************************************
7º) Tenemos que crearnos el fichero XML con los parámetros de configuración de la conexión con la Base de Datos MySql. Por defecto, el nombre de este fichero tendrá que ser hibernate.cfg.xml. En nuestro ejemplo, vamos a configurarlo de este modo.
<?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>
<!-- Propiedades de la Conexion a Base Datos -->
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.url">
jdbc:mysql://localhost:3306/universojava?useSSL=false&serverTimezone=UTC
</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="hibernate.show_sql">false</property>
<property name="hibernate.format_sql">true</property>
<property name="use_sql_comments">false</property>
<mapping class="com.universo.fichero.modelo.Valor" />
</session-factory>
</hibernate-configuration>
8º) A continuación, tenemos que generar la clase que se encargará de crear el objeto SessionFactory a partir de la configuración que hayamos definido en hibernate.cfg.xml. Posteriormente, el SessionFactory nos permitirá crear las sesiones necesarias para acceder a la Base de Datos.
// **************************************************
package com.universo.fichero.config;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistry;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
// Creacion de un objeto SessionFactory por cada almacen de datos
// El acceso al objeto SessionFactory se realiza mediante el metodo getSessionFactory()
public class HibernateUtil {
private static final SessionFactory sessionFactory = buildSessionFactory();
private static SessionFactory buildSessionFactory() {
try {
// Creacion de SessionFactory a partir del fichero "hibernate.cfg.xml"
// SessionFactory carga el fichero de configuracion, analiza el mapeo
// de entidades y crea la conexion con la base de datos
final StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
.configure("hibernate.cfg.xml")
.build();
SessionFactory sf =
new MetadataSources(registry).buildMetadata().buildSessionFactory();
return sf;
} catch (Throwable ex) {
System.err.println("Error al inicializar SessionFactory: " + ex);
throw new ExceptionInInitializerError(ex);
}
}
public static SessionFactory getSessionFactory() {
System.out.println("*** Obtener Factoria Hibernate ***");
return sessionFactory;
}
public static Session getSession() throws HibernateException {
Session session = sessionFactory.openSession();
return session;
}
public static void closeSessionFactory() {
System.out.println("*** Cerrar Factoria Hibernate ***");
sessionFactory.close();
}
}
// **************************************************
9º) Ahora procedemos a crearnos el repositorio donde se realizarán las diferentes operaciones de acceso a Base de Datos. En nuestro caso, nos crearemos una clase ValorRepo.java donde implementaremos un sencillo CRUD.
// **************************************************
package com.universo.fichero.repositorio;
import org.hibernate.Session;
import com.universo.fichero.config.HibernateUtil;
import com.universo.fichero.modelo.Valor;
public class ValorRepo {
// Crear valor
public void crear(Valor valor) {
System.out.println("Crear valor: " + valor.toString());
// abrir sesion
Session session = HibernateUtil.getSession();
session.beginTransaction();
session.save(valor);
// cerrar sesion
session.getTransaction().commit();
session.close();
}
// Obtener valor
public void obtener(long id) {
System.out.println("Obtener valor con Id: " + id);
// abrir sesion
Session session = HibernateUtil.getSession();
Valor valor = session.get(Valor.class, id);
System.out.println("Valor: " + valor.toString());
// cerrar sesion
session.close();
}
// Modificar valor
public void modificar(Valor valor) {
System.out.println("Actualizar valor: " + valor.toString());
// abrir sesion
Session session = HibernateUtil.getSession();
session.beginTransaction();
session.update(valor);
// cerrar sesion
session.getTransaction().commit();
session.close();
}
// Eliminar valor
public void eliminar(long id) {
System.out.println("Eliminar valor con Id: " + id);
Valor valor = new Valor();
valor.setId(id);
// abrir sesion
Session session = HibernateUtil.getSession();
session.beginTransaction();
session.delete(valor);
// cerrar sesion
session.getTransaction().commit();
session.close();
}
}
// **************************************************
Creación de clase de prueba del proyecto
10º) Vamos ahora a crearnos una clase para poder realizar algunas pruebas con el repositorio que nos acabamos de crear. La idea es validar que funcionan correctamente todas las operaciones de acceso a nuestra tabla "valor" de MySql.
Por tanto, nos creamos una clase main AppXml.java con la intención de obtener el contenido del Valor correspondiente al Id = 6.
// **************************************************
package com.universo.fichero.defecto;
import com.universo.fichero.config.HibernateUtil;
import com.universo.fichero.repositorio.ValorRepo;
public class AppXml {
public static void main(String[] args) {
// TODO Auto-generated method stub
ValorRepo repo = new ValorRepo();
// Identificadores
long valorId1 = 6;
// Abrir SessionFactory
HibernateUtil.getSessionFactory();
// Crud
repo.obtener(valorId1);
// Cerrar SessionFactory
HibernateUtil.closeSessionFactory();
}
}
// **************************************************
11º) Una vez creadas todas las clases anteriores, ya estaríamos en disposición de ejecutar nuestra aplicación. La estructura de nuestro proyecto debería quedar del siguiente modo.
Probando nuestra Configuración de Hibernate
12º) Si ejecutamos AppXml.java, nuestra aplicación debería acceder a la tabla "valor" y recuperar el Valor con Id = 6 (Facebook). La salida de la ejecución es la siguiente.
ago 02, 2021 4:30:05 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
ago 02, 2021 4:30:05 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
ago 02, 2021 4:30:05 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
ago 02, 2021 4:30:05 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
*** Obtener Factoria Hibernate ***
Obtener valor con Id: 6
Valor: Valor [id=6, nombre=Facebook, ticker=FB, indice=Nasdaq-100, pais=EEUU, rentabilidad=41.41]
*** Cerrar Factoria Hibernate ***
ago 02, 2021 4:30:06 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/universojava?useSSL=false&serverTimezone=UTC]
Tal y como se aprecia en la salida, el acceso a MySql ha recuperado el registro con id=6, que era justamente lo que esperábamos encontrar.
13º) Vamos a probar ahora el alta de registros. Para ello, en AppXml.java tendremos que incluir un código de este estilo. El objetivo es crear el registro correspondiente a la empresa "Berkshire".
// Valores
Valor valor1 = new Valor("Berkshire", "BRK.B", "Nasdaq-100", "EEUU", 42.14f);
// Abrir SessionFactory
HibernateUtil.getSessionFactory();
// Crud
repo.crear(valor1);
// Cerrar SessionFactory
HibernateUtil.closeSessionFactory();
Si ejecutamos el código anterior, en la consola de Eclipse deberíamos obtener una salida del siguiente modo.
ago 02, 2021 4:48:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
ago 02, 2021 4:48:55 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
ago 02, 2021 4:48:55 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
ago 02, 2021 4:48:56 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
*** Obtener Factoria Hibernate ***
Crear valor: Valor [id=null, nombre=Berkshire, ticker=BRK.B, indice=Nasdaq-100, pais=EEUU, rentabilidad=42.14]
*** Cerrar Factoria Hibernate ***
ago 02, 2021 4:48:56 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/universojava?useSSL=false&serverTimezone=UTC]
👉 Y, por supuesto, tras la ejecución del proceso el registro deberá haber quedado dado de alta en la Base de Datos MySql.
14º) Toca probar la actualización del MySql. En nuestro ejemplo, tenemos que corregir el error y asociar la empresa "Berkshire" al índice "SP500". Para ello, en la clase AppXml.java incluimos el siguiente código.
// Valores
Valor valor2 = new Valor(7l, "Berkshire", "BRK.B", "SP-500", "EEUU", 42.14f);
// Abrir SessionFactory
HibernateUtil.getSessionFactory();
// Crud
repo.modificar(valor2);
// Cerrar SessionFactory
HibernateUtil.closeSessionFactory();
Si ejecutamos el código anterior, en la consola de nuestro Eclipse deberíamos obtener una salida del siguiente modo.
ago 02, 2021 5:19:03 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
ago 02, 2021 5:19:03 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
ago 02, 2021 5:19:04 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
ago 02, 2021 5:19:04 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
*** Obtener Factoria Hibernate ***
Actualizar valor: Valor [id=7, nombre=Berkshire, ticker=BRK.B, indice=SP-500, pais=EEUU, rentabilidad=42.14]
*** Cerrar Factoria Hibernate ***
ago 02, 2021 5:19:04 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/universojava?useSSL=false&serverTimezone=UTC]
👉 Tras la ejecución del proceso, podremos comprobar que el registro ha quedado modificado en la Base de Datos MySql.
15º) Por último, vamos a probar la eliminación de registros de la Base de Datos. Para ello, procedemos a borrar uno de los valores existentes mediante la inclusión en AppXml.java del siguiente código.
// Identificadores
long valorId2 = 2;
// Abrir SessionFactory
HibernateUtil.getSessionFactory();
// Crud
repo.eliminar(valorId2);
// Cerrar SessionFactory
HibernateUtil.closeSessionFactory();
Si ejecutamos el código anterior, en la consola de nuestro Eclipse deberíamos obtener una salida del siguiente modo.
ago 02, 2021 5:29:41 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl buildCreator
INFO: HHH10001003: Autocommit mode: false
ago 02, 2021 5:29:41 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PooledConnections <init>
INFO: HHH000115: Hibernate connection pool size: 20 (min=1)
ago 02, 2021 5:29:41 PM org.hibernate.dialect.Dialect <init>
INFO: HHH000400: Using dialect: org.hibernate.dialect.MySQLDialect
ago 02, 2021 5:29:42 PM org.hibernate.engine.transaction.jta.platform.internal.JtaPlatformInitiator initiateService
INFO: HHH000490: Using JtaPlatform implementation: [org.hibernate.engine.transaction.jta.platform.internal.NoJtaPlatform]
*** Obtener Factoria Hibernate ***
Eliminar valor con Id: 2
*** Cerrar Factoria Hibernate ***
ago 02, 2021 5:29:42 PM org.hibernate.engine.jdbc.connections.internal.DriverManagerConnectionProviderImpl$PoolState stop
INFO: HHH10001008: Cleaning up connection pool [jdbc:mysql://localhost:3306/universojava?useSSL=false&serverTimezone=UTC]
👉 Tras la ejecución del proceso, podremos comprobar que el registro ha quedado eliminado de la Base de Datos MySql.
Con los pasos que acabamos de comentar ya deberíamos tener una idea más o menos clara de cuáles son las tareas que debemos realizar para elaborar un proyecto Maven con configuración XML de Hibernate. Obviamente, la estructura del proyecto se puede complicar mucho más, pero aquí tenemos todo lo necesario para implementar un CRUD básico. Con un poquito más de estudio por nuestra parte, deberíamos ir siendo capaces de ampliar la funcionalidad de nuestra aplicación Hibernate. Pero eso ya se saldría de los objetivos del presente post.
Pues nada, eso era todo lo que tenía que comentar en relación con la configuración XML de un proyecto Hibernate. El próximo día trataremos de ampliar el tema revisando los pasos a seguir para realizar una configuración mediante fichero Properties. Hasta entonces, cualquier duda podéis dejármela aquí abajo.
Saludos.
Comentarios
Publicar un comentario