Uso básico de Hibernate con Oracle y MySQL

En este artículo vamos a aprender a configurar el entorno de desarrollo para utilizar Hibernate con Eclipse y Oracle o MySQL desde cero. Además, crearemos una sencilla aplicación para ejemplificar cómo deben crearse los ficheros de configuración, modelo y mapeo de hibernate. En este ejemplo se utilizará hibernate sobre una sola tabla sin ningún tipo de relación con otras.

Hibernate es una herramienta de persistencia relacional para Java o herramienta de mapeo objeto relacional (ORM). Hibernate nos permite realizar de forma sencilla el mapeo de atributos entre nuestros objetos Java y una base de datos.

Antes de empezar, debemos descargar los siguientes archivos. En este punto deberemos decidir si queremos utilizar Oracle o MySQL para nuestro proyecto.

Instalación de Eclipse

Como ya sabéis, Eclipse no necesita instalación, con lo cual, bastará con descomprimir el zip descargado y colocar el directorio eclipse donde deseéis.

Instalación de Oracle

Si vamos a realizar nuestro proyecto con Oracle, deberemos realizar la instalación de éste mediante el paquete descargado. Es importante tener en cuenta que, durante la instalación, nos pedirá introducir la contraseña del usuario SYSTEM que va a ser necesario la primera vez que accedamos a Oracle o hasta que creemos un usuario nuevo tal y como hemos visto en manuales anteriores.

Instalación de MySQL

Si hemos decidido utilizar MySQL en nuestro proyecto, antes de realizar la instalación de MySQL debemos instalar el Framework .NET, de lo contrario, el instalador de MySQL no se iniciará. A continuación, iniciaremos la instalación de MySQL. Personalmente recomiendo también la instalación de MySQLWorkbench que se nos ofrecerá durante el proceso de instalación de MySQL. Para ello, a la hora de escoger que componentes van a instalar-se, escogeremos la instalación personalizada y dejaremos activas las opciones de MySQL y MySQLWorkbench, el resto de opciones (conectores, etc.) las vamos a desmarcar. Justo antes de iniciar la instalación, el instalador nos pedirá instalar Microsoft Visual C++ 2010 runtime, necesario para el Workbench. Este proceso se realizará automáticamente.

Finalmente, configuraremos la maquina como Developer Machine y habilitaremos el acceso remoto TCP/IP por si es necesario en un futuro, de no ser así, lo desactivaremos. Una vez hecha esta configuración, añadiremos  un password de root y crearemos un nuevo usuario con el que vamos a trabajar, vamos a asignarle el rol de DB Admin.

Instalación JDK 7

Para poder iniciar eclipse y, lógicamente, programar cualquier aplicación en Java será necesario instalar el JDK.

Configuración de un proyecto Hibernate

Vamos a crear un nuevo proyecto llamado Hibernate. Este proyecto lo usaremos como ejemplo de configuración en Eclipse.

En este proyecto, debemos añadir el conector de Oracle o  MySQL y las librerías necesarias de hibernate, para ello haremos clic derecho sobre el proyecto -> Properties -> Java Build Path -> Libraries. Hacemos clic en añadir jar externo para añadir el conector de Oracle o el de MySQL. Una vez añadido, repetimos el proceso para las librerías de hibernate. Deberemos añadir todos los jars que se encuentran en hibernate -> lib -> required.

Atención!: A partir de la versión 4.2 de hibernate en el directorio required no aparecen todas las librerías necesarias. Las librerías a añadir al classpath deben ser:

  • antlr-2.7.7.jar
  • dom4j-1.6.1.jar
  • hibernate-commons-annotations-4.0.1.Final.jar
  • hibernate-core-4.1.10.Final.jar
  • hibernate-jpa-2.0-api-1.0.1.Final.jar
  • javassist-3.15.0-GA.jar
  • jboss-logging-3.1.0.GA.jar
  • jboss-transaction-api_1.1_spec-1.0.0.Final.jar

Una vez creado el proyecto, le añadiremos un paquete desde el cual vamos a crear la siguiente estructura de paquetes. El paquete principal se va a llamar com.hibernate. A este paquete le añadiremos un nuevo paquete haciendo clic derecho sobre el proyecto y seleccionando New->Package. Este paquete va a contener los ficheros de modelo y de mapeo que usaremos con hibernate y será llamado “data”. A su vez, dentro de este paquete crearemos dos mas, uno llamado “mapeo” y otro llamado “modelo”. Con esto obtendremos la siguiente lista de paquetes:

  • com.hibernate
  • com.hibernate.data
  • com.hibernate.data.modelo
  • com.hibernate.data.mapeo

En el siguiente ejemplo crearemos un objeto Alumno que contendrá los datos necesarios de un alumno y utilizaremos hibernate para realizar la persistencia del objeto en la base de datos.

Creación del modelo

En el package data.modelo crearemos la clase java, los objetos de la cual vamos a “almacenar” en nuestra base de datos. Ésta clase deberá contener un conjunto de atributos privados así como métodos getters y setters para poder gestionarlos. Debemos incluir siempre un atributo llamado id que hará de identificador. El método setId deberá ser privado ya que solo hibernete debe ser capaz de utilizarlo. Llamaremos a esta clase Alumno.java.

package com.hibernate.data.modelo;

import java.util.Date;

public class Alumno {

    private Integer idalumno;//Para facilidad de uso de hibernate, 
                     //se recomienda NO tipos primitivos (p.e. Integer en lugar de int)
    private String nombre;
    private String apellidos;
    private String dni;
    private Date nacimiento;

    public Integer getIdalumno(){
        return idalumno;
    }
    /*
     * SetId es privado ya que SOLO hibernate debe encargarse de gestionar los id
     * de cada objeto
     */
    private void setIdalumno(Integer idalumno){
        this.idalumno = idalumno;
    }

    public String getNombre(){
        return nombre;
    }

    public void setNombre(String nombre){ 
        this.nombre = nombre;
    }

    public String getApellidos(){
        return apellidos;
    }

    public void setApellidos(String apellidos){
        this.apellidos=apellidos;
    }

    public String getDni(){
        return dni;
    }

    public void setDni(String dni){
        this.dni=dni;
    }

    public Date getNacimiento(){
        return nacimiento;
    }

    public void setNacimiento(Date nacimiento){
        this.nacimiento = nacimiento;
    }

}

Creación del mapeo

Crearemos un fichero llamado Alumno.hbm.xml (hibernate Mapping) en el cual vamos a relacionar cada uno de los atributos del modelo anterior con un atributo de la tabla MySQL. Este fichero lo vamos a crear dentro del paquete data.mapeo. Esta versión funcionaría correctamente en Oracle. La versión para MySQL la podemos encontrar a continuación de ésta.

Versión para Oracle:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <!-- Especificamos que modelo vamos a mapear en este archivo -->
    <class name="com.hibernate.data.modelo.Alumno" table="alumno">
        <!-- Especificamos que campo es el id -->
        <id name="idalumno" column="idalumno">
            <!-- Nos crea una secuencia de forma automática para este campo 
            La secuencia en este caso se llamara alumno_SQ_Hibernate-->
            <generator class="sequence">
                  <param name="sequence">alumno_SQ_Hibernate</param> 
            </generator> <!-- Native requiere autoincrement al otro lado (en BD)-->
        </id>
        <!-- Vamos añadiendo todos los atributos -->

        <property name="nombre">
        <!-- Si el atributo del modelo no tiene el mismo nombre que el atributo
        correspondiente en la BD, debemos especificar el nombre de la columna 
        con "column name". Además, podemos añadir opcionalmente cierta información
        como longitud o nulidad-->
            <column name="name" length="45" not-null="true" />
        </property> 

        <property name="apellidos"/>
        <property name="dni"/>
        <property name="nacimiento">
            <column name="fnacimiento" not-null="true" />
        </property>

    </class>
</hibernate-mapping>

Versión para MySQL:

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>
    <!-- Especificamos que modelo vamos a mapear en este archivo -->
    <class name="com.hibernate.data.modelo.Alumno" table="alumno">
        <!-- Especificamos que campo es el id -->
        <id name="idalumno" column="idalumno">
            <!-- Permite realizar un autoincrement automáticamente -->
            <generator class="identity"/> <!-- Native requiere autoincrement al otro lado (en BD) -->
        </id>
        <!-- Vamos añadiendo todos los atributos -->

        <property name="nombre">
        <!-- Si el atributo del modelo no tiene el mismo nombre que el atributo 
        correspondiente en la BD, debemos especificar el nombre de la columna 
        con "column name". Además, podemos añadir opcionalmente cierta información
        como longitud o nulidad-->
            <column name="name" length="45" not-null="true" />
        </property> 

        <property name="apellidos"/>
        <property name="dni"/>
        <property name="nacimiento">
            <column name="fnacimiento" not-null="true" />
        </property>

    </class>
</hibernate-mapping>

Configuración de Hibernate

Crearemos ahora un directorio llamado conf en nuestro proyecto fuera del directorio src. En ese directorio crearemos el fichero de configuración de Hibernate para este proyecto. El fichero se llamará hibernate.cfg.xml.

Versión para Oracle:

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Dialecto Hibernate -->
        <property name="hibernate.dialect">org.hibernate.dialect.Oracle10gDialect</property>

        <!-- Conexión a la base de datos -->
        <property name="hibernate.connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
        <property name="hibernate.connection.url">jdbc:Oracle:thin:@192.168.100.100:1521:XE</property>
        <property name="hibernate.connection.username">aitor</property>
        <property name="hibernate.connection.password">P@ssw0rd</property>
        <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

        <!-- Muestra por consola el código SQL usado por hibernate al trabajar con la BD -->
        <property name="show_sql">true</property>

        <!-- Creación de esquema automática. 
            validate: Valida el esquema, no crea la Base de datos, actualiza, elimina y añade registros
            update: Actualiza el esquema. Crea base de datos si no existe. No elimina esquema anterior.
            create: Crea siempre el esquema eliminando información anterior. Elimina la tabla y la vuelve a crear.
            create-drop: Elimina el esquema al final de la sesión.
        -->
        <property name="hibernate.hbm2ddl.auto">update</property>  

        <!-- Configurar la cache de hibernate -->
        <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>

        <!-- Se unirá la sesión al thread en el que se ha llamado -->
        <property name="current_session_context_class">thread</property>

        <!-- Indicamos el fichero de mapeo-->
        <mapping resource="com/hibernate/data/mapeo/Alumno.hbm.xml" />

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

Versión para MySQL:

<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
    <session-factory>

        <!-- Dialecto Hibernate 
        org.hibernate.dialect.MySQLInnoDBDialect -> No permite crear BD si no existe
        org.hibernate.dialect.MySQLDialect -> Permite crear BD si no existe
         -->
        <property name="hibernate.dialect">org.hibernate.dialect.MySQLDialect</property>

        <!-- Conexión a la base de datos -->
        <property name="hibernate.connection.driver_class">com.mysql.jdbc.Driver</property>
        <property name="hibernate.connection.url">jdbc:mysql://localhost:3306/hibernate</property>
        <property name="hibernate.connection.username">root</property>
        <property name="hibernate.connection.password">aitor</property>
        <property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>

        <!-- Creación de esquema automática (create, update). Si no existe la tabla en
        la BD la crea (create). Atención con utilizar create ya que, si la tabla existe,
        la borrará y creará de nuevo!-->
        <property name="hibernate.hbm2ddl.auto">update</property>  

        <!-- Configuramos la cache de hibernate -->
        <property name="hibernate.cache.provider_class">org.hibernate.cache.HashtableCacheProvider</property>

        <!-- Se unirá la sesión al thread en el que se ha llamado -->
        <property name="current_session_context_class">thread</property>

        <!-- Indicamos el fichero de mapeo-->
        <mapping resource="com/hibernate/data/mapeo/Alumno.hbm.xml" />

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

Una vez creado el fichero de configuración, debemos incluir el directorio conf en el classpath del proyecto. Para ello, seguiremos los mismos pasos que para agregar las librerías de hibernate pero, una vez en la pestaña libraries, escogeremos “Add Class Folder” y  seleccionaremos el directorio conf del proyecto.

Cliente

Crearemos ahora la clase que utilizará hibernate para instanciar nuevos Alumnos y guardarlos en la Base de Datos.

package com.hibernate;
import java.util.Date;
import java.util.List;
import java.util.Map;
import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;

import com.hibernate.data.modelo.Alumno;

public class TrabajoConAlumnos {
   private static final SessionFactory sessionFactory;

   public static void main(String[] args) {
      Session session = getSessionFactory().getCurrentSession();

      createAlumnos(session);

      //Hemos cerrado la sesión anterior, hay que volver a crearla
      session = getSessionFactory().getCurrentSession();
      Transaction t = session.beginTransaction();

      getAlumnos(session);
      eliminarAlumno(session);

      t.commit(); 
      //session.close();
   }
   public static void createAlumnos(Session session) {
      Alumno alumno1 = new Alumno(); //Creamos un nuevo alumno
      alumno1.setNombre("Elena");
      alumno1.setApellidos("Garcia");
      alumno1.setDni("00000000A");
      alumno1.setNacimiento(new Date());
      //alumno.setIdalumno(1); No se puede hacer ya que es private

      //Iniciamos una transacción
      session.beginTransaction();

      //Guardamos el alumno en la base de datos 
      session.save(alumno1);

      /*
       * Creamos dos alumnos más, éstos los vamos
       * a guardar a la vez usando persist.
       */
      Alumno alumno2 = new Alumno();
      alumno2.setNombre("Laura");
      alumno2.setApellidos("Lopez");
      alumno2.setDni("00000000B");
      alumno2.setNacimiento(new Date());

      Alumno alumno3 = new Alumno();
      alumno3.setNombre("Ferran");
      alumno3.setApellidos("Adria");
      alumno3.setDni("00000000C");
      alumno3.setNacimiento(new Date());

      session.persist(alumno2); 
      session.persist(alumno3); 

      /* Confirmamos los tres alumnos.
       * 
       * Si no hacemos un commit se insertaran los alumnos
       * pero al destruir el objeto después de la ejecución, 
       * todo lo que esté sin commit se hará rollback automaticamente
       *
       * Al hacer commit, la sesión se cierra y se deberá volver a crear!
       */
      session.getTransaction().commit(); 

      //No es necesario el close() a causa del commit anterior!
      //session.close();   
   }

   private static void getAlumnos(Session session) {
      /*
      * CONSULTAS EN SQL
      * Se puede usar SQL para hacer consultas a la base de datos
      */ 
      String sql = "SELECT idalumno, fnacimiento FROM alumno where dni='00000000C'";
      SQLQuery query = session.createSQLQuery(sql);
      query.setResultTransformer(Criteria.ALIAS_TO_ENTITY_MAP);

      List results = query.list();
      for(Object object : results) {
         Map row = (Map)object;
         System.out.print("ID Alumno: " + row.get("IDALUMNO"));
         System.out.println(", Nacimiento: " + row.get("FNACIMIENTO"));
      }
     /*
      * También podemos utilizar HQL (Hibernate Query Language) para realizar consultas
      *
      * No se puede usar select * para obtener todas las columnas de la tabla,
      * si se quieren obtener todas debe omitirse el select y realizar la
      * consulta como: "FROM Alumno where..."
      * En este caso, Alumno se escribe con la primera letra en mayusculas
      * ya que en HQL no nos referimos a la tabla sino al objecto (clase) Alumno!
      *   String hql = "select nombre FROM Alumno where dni='00000000C'";
      *   Query queryHql = session.createQuery(hql);
      *   List n = queryHql.list();
      *   System.out.println(n.get(0).toString());
      */
      String hql = "FROM Alumno where dni='00000000C'";
      Query queryHql = session.createQuery(hql);
      List <Alumno> alumnos = queryHql.list();
      java.util.Iterator<Alumno> iter = alumnos.iterator();

      while (iter.hasNext()) {
         Alumno alumno = iter.next();
         //Obtenemos un objeto Alumno, podemos modificar sus atributos directamente!
         //Se actualizará la base de datos con un nuevo valor en el atributo
         alumno.setNombre("Luisa");
         System.out.println("\nNombre: " + alumno.getNombre() +
         "\nApellidos:" + alumno.getApellidos() +"\nDNI: " +
         alumno.getDni()+"\nNacimiento: "+alumno.getNacimiento()+"\n");
      }
   }

   public static void eliminarAlumno(Session session){
       /*
       * Eliminamos alumnos con DNI '00000000I'
       */
      String hql = "FROM Alumno where dni='00000000I'";
      Query queryHql = session.createQuery(hql);
      List <Alumno> alumnos = queryHql.list();
      java.util.Iterator<Alumno> iter = alumnos.iterator();

      while (iter.hasNext()) {
          Alumno alumno = iter.next();
          session.delete(alumno);
      }
   }

   public static SessionFactory getSessionFactory() {
          return sessionFactory;
   }

   static {
      try {
         // Creamos la SessionFactory desde hibernate.cfg.xml
         Configuration configuration = new Configuration().configure();
         ServiceRegistry serviceRegistry = new ServiceRegistryBuilder()
         .applySettings(configuration.getProperties()).buildServiceRegistry();
         sessionFactory = configuration.buildSessionFactory(serviceRegistry);
      } catch (Throwable ex) {
         System.err.println("Error en la creación de SessionFactory: " + ex);
         throw new ExceptionInInitializerError(ex);
      }
   }
}

Con esta clase podemos crear un nuevo alumno e introducirlo en nuestra base de datos. Hay que tener en cuenta que, si no existe la tabla, tal y como hemos configurado hibernate en el fichero de mapeo, ésta se creará automáticamente.

Una vez hemos introducido un nuevo alumno, se va a consultar la información de éste mismo alumno utilizando SQL y, posteriormente, HQL. Hay que observar cómo, al trabajar con HQL, podemos obtener un objeto Alumno sobre el que poder trabajar directamente. Cualquier modificación que realicemos a un Alumno obtenido aquí, será automáticamente reflejado en la base de datos sin necesidad de hacer un save explícito.

Enlaces de interés

Anuncios

2 Responses to Uso básico de Hibernate con Oracle y MySQL

  1. Pingback: Hibernate con relaciones 1 a 1 unidireccionales | Aitor Rigada

  2. Pingback: Hibernate con relaciones 1 a N unidireccionales | Aitor Rigada

Responder

Introduce tus datos o haz clic en un icono para iniciar sesión:

Logo de WordPress.com

Estás comentando usando tu cuenta de WordPress.com. Cerrar sesión / Cambiar )

Imagen de Twitter

Estás comentando usando tu cuenta de Twitter. Cerrar sesión / Cambiar )

Foto de Facebook

Estás comentando usando tu cuenta de Facebook. Cerrar sesión / Cambiar )

Google+ photo

Estás comentando usando tu cuenta de Google+. Cerrar sesión / Cambiar )

Conectando a %s

A %d blogueros les gusta esto: