Primeros pasos con hibernación

Uso de la configuración XML para configurar Hibernate

Creo un archivo llamado database-servlet.xml en algún lugar del classpath.

Inicialmente, su archivo de configuración se verá así:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:jdbc="http://www.springframework.org/schema/jdbc"
xmlns:tx="http://www.springframework.org/schema/tx"
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans-3.2.xsd
    http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc-3.2.xsd
    http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx-3.2.xsd">

</beans>

Notarás que importé los espacios de nombres Spring tx y jdbc. Esto se debe a que los usaremos bastante en este archivo de configuración.

Lo primero que debe hacer es habilitar la gestión de transacciones basada en anotaciones ("@Transactional"). La razón principal por la que las personas usan Hibernate en Spring es porque Spring administrará todas sus transacciones por usted. Agregue la siguiente línea a su archivo de configuración:

<tx:annotation-driven />

Necesitamos crear una fuente de datos. La fuente de datos es básicamente la base de datos que Hibernate utilizará para conservar sus objetos. Generalmente, un administrador de transacciones tendrá una fuente de datos. Si desea que Hibernate hable con múltiples fuentes de datos, entonces tiene múltiples administradores de transacciones.

<bean id="dataSource" 
    class="org.springframework.jdbc.datasource.DriverManagerDataSource">
    <property name="driverClassName" value="" />
    <property name="url" value="" />
    <property name="username" value="" />
    <property name="password" value="" />
</bean>

La clase de este bean puede ser cualquier cosa que implemente javax.sql.DataSource para que pueda escribir la suya propia. Spring proporciona esta clase de ejemplo, pero no tiene su propio grupo de subprocesos. Una alternativa popular es Apache Commons org.apache.commons.dbcp.BasicDataSource, pero hay muchas otras. Te explico cada una de las propiedades a continuación:

  • driverClassName: La ruta a su controlador JDBC. Este es un JAR específico de la base de datos que debería estar disponible en su classpath. Asegúrese de tener la versión más actualizada. Si está utilizando una base de datos de Oracle, necesitará un OracleDriver. Si tiene una base de datos MySQL, necesitará un MySQLDriver. Vea si puede encontrar el controlador que necesita [aquí] 1 pero un rápido google debería darle el controlador correcto.

  • url: La URL de su base de datos. Por lo general, será algo como jdbc\:oracle\:thin\:\path\to\your\database o jdbc:mysql://path/to/your/database. Si busca en Google la ubicación predeterminada de la base de datos que está utilizando, debería poder averiguar cuál debería ser. Si recibe una HibernateException con el mensaje org.hibernate.HibernateException: la conexión no puede ser nula cuando 'hibernate.dialect' no está establecido y está siguiendo esta guía, hay un 90% de posibilidades de que su URL sea incorrecta. un 5% de probabilidad de que su base de datos no esté iniciada y un 5% de probabilidad de que su nombre de usuario/contraseña sea incorrecto.

  • nombre de usuario: El nombre de usuario a utilizar al autenticarse con la base de datos.

  • contraseña: La contraseña a utilizar al autenticarse con la base de datos.

Lo siguiente es configurar SessionFactory. Esto es lo que utiliza Hibernate para crear y administrar sus transacciones, y en realidad se comunica con la base de datos. Tiene bastantes opciones de configuración que intentaré explicar a continuación.

<bean id="sessionFactory"
    class="org.springframework.orm.hibernate4.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource" />
    <property name="packagesToScan" value="au.com.project />
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.use_sql_comments">true</prop>
            <prop key="hibernate.hbm2ddl.auto">validate</prop>
        </props>
    </property>
</bean>
  • dataSource: Su bean fuente de datos. Si cambió el Id. de la fuente de datos, configúrelo aquí.

  • packagesToScan: Los paquetes a escanear para encontrar sus objetos anotados JPA. Estos son los objetos que la fábrica de sesiones necesita administrar, generalmente serán POJO y anotados con @Entity. Para obtener más información sobre cómo configurar relaciones de objetos en Hibernate ver aquí.

  • clases anotadas (no se muestra): también puede proporcionar una lista de clases para que Hibernate las escanee si no están todas en el mismo paquete. Debe usar packagesToScan o annotatedClasses pero no ambos. La declaración se ve así:

<property name="annotatedClasses">
    <list>
        <value>foo.bar.package.model.Person</value>
        <value>foo.bar.package.model.Thing</value>
    </list>
</property>
  • hibernateProperties: Hay una miríada de estos todos amorosamente documentados aquí. Los principales que utilizará son los siguientes:
  • hibernate.hbm2ddl.auto: una de las preguntas más candentes de Hibernate detalla esta propiedad. Véalo para más información. Generalmente uso validar y configuro mi base de datos usando scripts SQL (para una memoria) o creo la base de datos de antemano (base de datos existente).
  • hibernate.show_sql: indicador booleano, si es verdadero, Hibernate imprimirá todo el SQL que genera en stdout. También puede configurar su registrador para que le muestre los valores que se vinculan a las consultas configurando log4j.logger.org.hibernate.type=TRACE log4j.logger.org.hibernate.SQL=DEBUG en su administrador de registro (Yo uso log4j).
  • hibernate.format_sql: indicador booleano, hará que Hibernate imprima bastante su SQL en la salida estándar.
  • hibernate.dialect (No se muestra, por una buena razón): muchos tutoriales antiguos le muestran cómo configurar el dialecto de Hibernate que utilizará para comunicarse con su base de datos. Hibernate puede detectar automáticamente qué dialecto usar según el controlador JDBC que esté usando. Dado que hay alrededor de 3 dialectos de Oracle diferentes y 5 dialectos de MySQL diferentes, dejaría esta decisión en manos de Hibernate. Para obtener una lista completa de los dialectos compatibles con Hibernate ver aquí.

Los últimos 2 frijoles que necesita declarar son:

<bean class="org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor"
    id="PersistenceExceptionTranslator" />

<bean id="transactionManager" 
    class="org.springframework.orm.hibernate4.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory" />
</bean>

El PersistenceExceptionTranslator traduce las HibernateException o SQLExceptions específicas de la base de datos en excepciones de Spring que pueden ser entendidas por el contexto de la aplicación.

El bean TransactionManager es lo que controla las transacciones, así como las reversiones.

Nota: Debería conectar automáticamente su bean SessionFactory a sus DAO.

Configuración de Hibernate sin XML

Este ejemplo ha sido tomado de aquí

package com.reborne.SmartHibernateConnector.utils;

import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class LiveHibernateConnector implements IHibernateConnector {

    private String DB_DRIVER_NAME = "";
    private String DB_URL = "jdbc:h2:~/liveDB;MV_STORE=FALSE;MVCC=FALSE";
    private String DB_USERNAME = "sa";
    private String DB_PASSWORD = "";
    private String DIALECT = "org.hibernate.dialect.H2Dialect";
    private String HBM2DLL = "create";
    private String SHOW_SQL = "true";
    
    private static Configuration config;
    private static SessionFactory sessionFactory;
    private Session session;
    
    private boolean CLOSE_AFTER_TRANSACTION = false;

    public LiveHibernateConnector() {
        
        config = new Configuration();

        config.setProperty("hibernate.connector.driver_class",         DB_DRIVER_NAME);
        config.setProperty("hibernate.connection.url",                 DB_URL);
        config.setProperty("hibernate.connection.username",         DB_USERNAME);
        config.setProperty("hibernate.connection.password",         DB_PASSWORD);
        config.setProperty("hibernate.dialect",                     DIALECT);
        config.setProperty("hibernate.hbm2dll.auto",                 HBM2DLL);
        config.setProperty("hibernate.show_sql",                    SHOW_SQL);
    
        /*
         * Config connection pools
         */

        config.setProperty("connection.provider_class", "org.hibernate.connection.C3P0ConnectionProvider");
        config.setProperty("hibernate.c3p0.min_size", "5");
        config.setProperty("hibernate.c3p0.max_size", "20");
        config.setProperty("hibernate.c3p0.timeout", "300");
        config.setProperty("hibernate.c3p0.max_statements", "50");
        config.setProperty("hibernate.c3p0.idle_test_period", "3000");
        
        
        /**
         * Resource mapping
         */
        
//        config.addAnnotatedClass(User.class);
//        config.addAnnotatedClass(User.class);
//        config.addAnnotatedClass(User.class);
    
        sessionFactory = config.buildSessionFactory();
    }


    public HibWrapper openSession() throws HibernateException {
        return new HibWrapper(getOrCreateSession(), CLOSE_AFTER_TRANSACTION);
    }


    public Session getOrCreateSession() throws HibernateException {
        if (session == null) {
            session = sessionFactory.openSession();
        }
        return session;
    }

    public void reconnect() throws HibernateException {
        this.sessionFactory = config.buildSessionFactory();
    }

    
}

Tenga en cuenta que con la última versión de Hibernate, este enfoque no funciona bien (la versión 5.2 de Hibernate aún permite esta configuración)

Ejemplo simple de hibernación usando XML

Para configurar un proyecto de hibernación simple usando XML para las configuraciones, necesita 3 archivos, hibernate.cfg.xml, un POJO para cada entidad y un EntityName.hbm.xml para cada entidad. Aquí hay un ejemplo de cada uno usando MySQL:

hibernate.cfg.xml

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration PUBLIC 
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
   </property>
   <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
   </property>

   <property name="hibernate.connection.url">
      jdbc:mysql://localhost/DBSchemaName
   </property>
   <property name="hibernate.connection.username">
      testUserName
   </property>
   <property name="hibernate.connection.password">
      testPassword
   </property>

   <!-- List of XML mapping files -->
   <mapping resource="HibernatePractice/Employee.hbm.xml"/>

</session-factory>
</hibernate-configuration>

Se reemplazarían DBSchemaName, testUserName y testPassword. Asegúrese de usar el nombre completo del recurso si está en un paquete.

Empleado.java

package HibernatePractice;

public class Employee {
    private int id;
    private String firstName;
    private String middleName;
    private String lastName;
    
    public Employee(){
        
    }
    public int getId(){
        return id;
    }
    public void setId(int id){
        this.id = id;
    }
    public String getFirstName(){
        return firstName;
    }
    public void setFirstName(String firstName){
        this.firstName = firstName;
    }
    public String getMiddleName(){
        return middleName;
    }
    public void setMiddleName(String middleName){
        this.middleName = middleName;
    }
    public String getLastName(){
        return lastName;
    }
    public void setLastName(String lastName){
        this.lastName = lastName;
    }
}

Empleado.hbm.xml

<hibernate-mapping>
   <class name="HibernatePractice.Employee" table="employee">
      <meta attribute="class-description">
         This class contains employee information. 
      </meta>
      <id name="id" type="int" column="empolyee_id">
         <generator class="native"/>
      </id>
      <property name="firstName" column="first_name" type="string"/>
      <property name="middleName" column="middle_name" type="string"/>
      <property name="lastName" column="last_name" type="string"/>
   </class>
</hibernate-mapping>

Nuevamente, si la clase está en un paquete, use el nombre completo de la clase nombrePaquete.NombreClase.

Una vez que tenga estos tres archivos, estará listo para usar Hibernate en su proyecto.