Soy nuevo en esto de Hibernate, y tampoco he trabajado demasiado con Netbeans. Por eso es para mí todo un reto tratar de hacer un tutorial de Hibernate con Netbeans.

Por otra parte, tiene sus ventajas: no voy a poder dar nada por asumido, dado que no sé nada de nada. He estado haciendo unas pruebas y tal, pero no he conseguido nada funcional. Vamos a ver qué tal el tutorial.

No voy a tratar de explicar Hibernate. Eso ya lo hace muy bien la gente de Hibernate ( y tienen muy buenos tutoriales). Este tutorial trata exclusivamente de ver qué diferencias hay entre el citado tutorial y NetBeans.

Tan solo matizar que voy a suponer que estáis en un entorno GNU/Linux, bien Debian o bien Ubuntu.

Pasos previos

Antes de comenzar necesitamos unas cuantas herramientas:

  • NetBeans. Uso la versión 6.8.
  • El plugin para NetBeans con hibernate
  • Un servidor hsqldb.

Como voy a empezar desde el principio, veamos qué es cada cosa. Si eres muy listo te lo puedes saltar.

NetBeans

Descargaros NetBeans. De los “sabores” a elegir… pues realmente da igual. Por ser masocas vamos a elegir Java SE, que es el que menos cosas tiene.

Cuando lo tengáis, basta con ejecutar el programa que os habéis descargado:

$ ./netbeans-6.8-ml-javase-linux.sh

seguramente se os habrá instalado en /usr/local/netbeans-6.8, así que ejecutamos:

$ /usr/local/netbeans-6.8/bin/netbeans

Plugin hibernate

Para mi horror, han traducido “hibernate” como “hibernar”, por lo que no os extrañe si véis “hibernar” donde deberían haber puesto “hibernate”.

Dentro de NetBeans, vamos a Herramientas→Complementos, en el tab “Plugins disponibles” buscamos “hibernate”. Si no lo encontramos, nos vamos a la pestaña “Instalado”. El caso es que lo marcamos y comprobamos que se encuentre instalado y activado.

Servidor HSQLDB

GNU/Linux es muy complicado. Para instalaros el servidor, tenéis que seguir tooooooodos los siguientes pasos:

# apt-get install hsqldb-server

Tened cuidado, a ver si os vais a saltar algún paso… En fin. Ahora hay que echarlo a andar:

# /etc/init.d/hsqldb-server restart

Si queréis ver dónde está escuchando, mirad en /etc/hsqldb/sqltool.rc. Os harán falta privilegios de superusuario. Por defecto será algo como jdbc:hsqldb:http://localhost:8080/.

Programando

Volvamos a NetBeans.

Creamos un proyecto, al que vamos a llamar “hbtutorial”. Será una aplicación java sin más historia.

Configuración de la conexión

Ahora necesitamos configurar la conexión. Para ello hay distintas formas: un archivo properties, un archivo XML o incluso de forma programática. Vamos a usar la forma “NetBeans”, que también es la más extendida y un término medio entre potencia y sencillez: XML.

Para ello añadiremos un nuevo fichero al proyecto. El tipo será “otro”, para que nos salga el asistente. Dentro de este asistente tendremos que buscar la categoría “hibernate” y el tipo de archivo “Asistente para la configuración de Hibernate”. Pulsamos “siguiente”.

Dejaremos el nombre por defecto (hibernate.cfg), ya que no nos va a afectar demasiado, y volvemos a pulsar “siguiente”.

Aquí viene lo más complicado de todo. En la Conexión con base de datos, seleccionaremos Nueva Conexión con Base de datos…, con lo que se nos abrirá un nuevo asistente. El controlador va a ser Nuevo controlador, lo que volverá a abrir, una vez más, un asistente. Agregaremos /usr/share/java/hsqldb.jar. Veréis que se rellenan todos los campos, así que podemos aceptar. Estaremos en la ventana de nueva conexión, así que seleccionamos el controlador “HSQLDB” (In-Memory), nombre de usuario “sa” (acordaos del archivo /etc/hsqldb/sqltool.rc) y la URL de consexión jdbc:hsqldb:http://localhost:8080/. Pulsamos aceptar y debería conectar sin problemas.

Nos abrirá el editor de XML que vamos a ignorar de momento.

Helpers

Vamos a añadir un helper. Para ello volvemos a añadir un archivo, categoría hibernate, tipo de archivo HibernateUtil.java. El nombre de la clase será “HibernateUtil”, y lo metemos en el paquete “hbtutorial”. Si cotilleais, veréis que es una factory sin más.

Primera clase

Vamos a crearnos una clase para transformarla en una tabla. Vamos a definir una persona. Para ello añadimos un nuevo archivo, de categoría Java, de tipo Java Class, llamada Persona y en el paquete hbtutorial:

package hbtutorial;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;

public class Persona implements Serializable {
    private Long id;

    private String nombre;
    private String apellido1;
    private String apellido2;
    private String email;
    private String telefono;

}

Hemos dicho que vamos a usar hibernate, ¿no? Pues al lío. Ahora ALT+insertar o bien botón derecho del ratón y seleccionamos “Insertar código”. Seleccionamos “Getter y Setter” y marcamos directamente la clase (lo que marcará todo). pulsamos aceptar y nos generará un montón de funciones. Buscamos la función setId y, como recomienda la gente de Hibernate, la hacemos privada para no equivocarnos en el futuro.

Además, vamos a hacer que el nombre sea obligatorio. Para ello, volvemos a pulsar ALT+Insertar y seleccionamos “Constructor”. En la lista de campos, seleccionamos sólo el nombre y así tenemos que el constructor nos está exigiendo el nombre.

El “Mapping File”

Vamos a mapear nuestra clase contra una tabla. Para ello volvemos a crear un nuevo archivo, de categoría hibernate y de tipo Asistente de mapas de hibernate, que llamaremos persona.hbm y guardaremos en src. La clase a mapear es la única que tenemos: hbtutorial.Persona. Y no hay tabla que seleccionar, así que hemos terminado.

La verdad es que nos ha servido para poco… Tendré que investigar cómo se hace esto. Mas adelante me ha dado problemas y he tenido que sustituir el archivo por el siguiente:

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
  "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="hbtutorial">
    <class name="hbtutorial.Persona" table="persona">
        <id name="id" column="PERSON_ID">
            <generator class="native"/>
        </id>
        <property name="nombre"/>
        <property name="apellido1"/>
        <property name="apellido2"/>
        <property name="email"/>
        <property name="telefono"/>
    </class>
</hibernate-mapping>

Clase Main

Ahora nos vamos al archivo Main.java, que será donde tengamos la clase principal, y vamos a ver si somos capaces de crear alguna Persona.

package hbtutorial;

import org.hibernate.Criteria;
import org.hibernate.Session;

public class Main {

    public static void main(String[] args) {
        String [] people = {"Paco", "Juan"};
        String [] people2 = {"Maria", "Ana"};

        getPeople ();
        addPeople ( people );
        getPeople ();
        addPeople ( people2 );
        getPeople ();
    }

    public static void addPeople (String [] people) {
        Session session = MyHibernateUtil.getSessionFactory().getCurrentSession();

        for (String person : people)
        {
            session.beginTransaction ();
            Persona person_obj = new Persona ( person );
            session.save ( person_obj );
        }
    }

    public static void getPeople () {
        Session session = MyHibernateUtil.getSessionFactory().getCurrentSession();
        session.beginTransaction ();
        Criteria criteria = session.createCriteria ( Persona.class );
        System.out.println ("Personas encontradas:" + criteria.list ().size ());
        for ( Object persona_obj : criteria.list () )
        {
            Persona persona = (Persona) persona_obj;
            System.out.println ( " - " + persona.getNombre () );
        }
        session.getTransaction ().commit ();
    }
}

Se puede observar que hay dos funciones estáticas que permiten añadir personas o bien obtener la lista de personas. Para demostrar que estamos añadiendo personas, lo que he hecho es llamar a la función de obtención de personas 2 veces, y obtendremos un resultado similar a este:

Personas encontradas:0
Personas encontradas:2
 - Paco
 - Juan
Personas encontradas:4
 - Paco
 - Juan
 - Maria
 - Ana

Posibles problemas

socket creation error

Probablemente no hayamos levantado el servidor.

No CurrentSessionContext configured!

Podemos configurar Hibernate para que lo haga automáticamente, añadiendo al hibernate.cfg.xml la propiedad siguiente:

<property name="current_session_context_class">thread</property>

Después tendremos que limpiar el proyecto antes de volver a probar.

Unknown entity: hbtutorial.Persona

Por alguna razón, no está encontrando el archivo Persona.hbm.xml. Comprobad nombres, asegurad que está referenciado desde el hibernate.cfg.xml como un mapping, ….

Table not found in statement

Hemos tratado de acceder, pero la tabla no se ha creado aún. Probad a hacer un insert en la tabla antes de hacer un criteria. Si eso no funcionara, probad con

<property name="hibernate.hbm2ddl.auto">update</property>

o bien:

<property name="hibernate.hbm2ddl.auto">create</property>

Mucho ojo con estas claves… Informaros bien antes de usar el “create” o podréis perder datos.

Distintas filosofías

He descubierto que con Hibernate hay dos maneras de hacer las cosas:

  1. Partir del XML de mappings, con el que se generarán los POJOs y se puede configurar Hibernate para crear automáticamente la base de datos.
  2. Partir de la base de datos, desde la que obtenemos por ingeniería inversa el XML y los POJOs.

En mi opinión, la última de las opciones está bien cuando ya tenemos un sistema que no usa Hibernate y queremos importarlo rápidamente, pero no debería ser la opción habitual.

Por temas de mantenimiento, considero que es mejor mantener el XML y generar los POJOs por cada modificación. Esto es algo que se puede automatizar mediante Ant o Maven.

Un consejo es que cada POJO tenga asociada una clase que herede de él y que será donde hagamos todas las modificaciones que necesitemos. A menudo estas clases se llaman como el POJO pero acabados en I mayúscula.

Tengo que investigar más sobre cómo obtener los POJOs a partir del mapping file, ya que no debe ser difícil. Os lo contaré en otro artículo (si alguien lo sabe, bienvenido sea…).