Eventos en Hibernate (parte I)

0
22718

Eventos en Hibernate (Parte I)

Índice de contenidos

1. Introducción

2. Entorno

3. Preparando una
aplicación de ejemplo

3.1. Usando
Maven para crear el proyecto

3.2. Creando
el modelo

3.3. Creando
clases de prueba y probando la aplicación

4. Creando un oyente para escuchar

5. Dos mejor que uno

6. Conclusiones

1. Introducción

Este es el primero de una serie de tutoriales en los que vamos a hablar
del manejo de eventos en Hibernate. En este primer tutorial nos vamos a
centrar en los oyentes (listeners) que pueden utilizarse con una
SessionFactory para capturar los eventos que se producen al cargar una
entidad, guardarla, actualizarla, borrarla, etc. y realizar
algún tipo de acción en ese momento. En el
próximo tutorial veremos cómo asociar
métodos de retrollamada en nuestras entidades
a determinados eventos, de manera que éstos
métodos se ejecutarán al producirse los eventos
correspondientes. Esto útlimo además puede hacerse
por medio de anotaciones que siguen la especificación de EJB3.

2. Entorno

Para la realización de este tutorial se han utilizado
las siguientes herramientas:

  • Hardware: Portátil Asus G50Vseries (Core Duo
    P8600 2.4GHz, 4GB RAM, 320 GB HD).

  • Sistema operativo: Windows Vista Ultimate.

  • Eclipse Ganymede 3.4.1, con el plugin Q (http://code.google.com/p/q4e)
    para Maven

  • JDK 1.6.0

  • Maven 2.0.9

  • MySql 5.1.30

  • Hibernate 3

3. Preparando una
aplicación de ejemplo

3.1. Usando Maven para
crear el proyecto

Para mostrar el uso de los oyentes de eventos vamos a realizar
una sencilla aplicación Java que introduzca una serie de
usuarios en una base de datos y que después los recupere y los
muestre por la salida estándar.

Creamos un nuevo proyecto Maven, al que llamaremos
EventosHibernateI,
marcamos la casilla para crear un simple proyecto Java y pulsamos
finalizar.

Nuevo proyecto Maven

Editamos el fichero pom.xml para añadir las
dependencias necesarias para utilizar Hibernate y MySql.
Además, cambiamos el nivel de compilación por defecto
utilizado por Maven para poder utilizar anotaciones con Hibernate.

3.2 Creando el modelo

Ahora crearemos nuestro modelo, consistente de una
única entidad Usuario, la cual
será manejada por Hibernate para persistir los usuarios en la
base de datos. La entidad tendrá los campos nombre,
apellidos, fecha de nacimiento y edad.

El campo edad se marca como Transient para que Hibernate no lo
guarde en la base de datos. Este campo será calculado mediante
la función «calcularEdad» en base al valor de la fecha de
nacimiento. Más adelante veremos como conseguir que
está función sea llamada automáticamente al
producirse el evento PostLoad, que ocurre justo después de la
carga de los datos de la entidad.

Nota: deberemos cambiar el nivel de compilación en
Eclipse
como mínimo al 1.5, si no lo está ya,
para soportar las anotaciones.

Ahora que tenemos una bonita entidad para persistir, vamos a
crearnos un simple DAO que nos permita guardar un usuario en la base de
datos y recuperar la lista de usuarios.

Añadimos dentro de la carpeta resources el fichero de configuración de Hibernate.

Hemos añadido la propiedad hibernate.hbm2ddl.auto con el valor auto para que
Hibernate cree de manera automática las tablas en caso de que no existan.
Eso sí, no debemos olvidar crear primero el esquema eventos en la base de datos.

3.3 Creando clases de
prueba y probando la aplicación

Ahora crearemos un par de clases para probar el funcionamiento
de nuestra aplicación. La primera clase guardará una
serie de usuarios en la base de datos. La segunda recuperará
la lista de usuarios y mostrará por la consola su nombre,
apellidos y edad.

Aquí está el código de nuestra
clase PruebaInsercion.

Y aquí tenemos la clase PruebaListado, que
mostrará el nombre, apellidos y edad de los usuarios obtenidos
de la base de datos.

Ejecutamos primero la inserción y comprobamos que se
han añadido correctamente los usuarios a nuestra base de datos:

Listado de usuarios en base de datos

Ahora ejecutamos la prueba de listado y observamos…
¡Cáspita! O todos nuestros usuarios son
recién
nacidos o creo que hemos cometido algún error 😉

Listado de usuarios con edad igual a cero

Efectivamente, dijimos que íbamos a hacer que la
función «calcularEdad» se disparase de forma
«automática» al cargar nuestra entidad. ¿Y no era
este un tutorial de eventos en Hibernate?.

Hasta ahora sólamente hemos visto el uso normal de
Hibernate para persistir entidades. A continuación vamos a ver
cómo configurar un oyente para que se ejecute al
dispararse un determinado
evento.

4. Creando un oyente para
escuchar

Una vez preparada nuestra aplicación
sólamente nos resta crear una clase oyente que se ejecute al
cargar cada entidad Usuario. El oyente se encargará de
actualizar el valor de la edad del usuario en función de su
fecha de nacimiento.

Los oyentes en Hibernate son en la práctica
singletons, por lo que
pueden ser compartidos entre peticiones y por tanto no
deberían guardar
ningún tipo de estado.

Nuestro implementa la interfaz PostLoadEventListener, para
capturar este tipo de evento. También podríamos haber
extendido la clase PostLoadEvent, el oyente predeterminado de Hibernate.

En Hibernate existem básicamente eventos por
cada método de la clase Session (guardar, borrar, buscar…).
A continuación se muestra una tabla con todos los eventos
existentes:

Evento
Delete PostInsert
DirtyCheck PostLoad
Evict PostUpdate
Flush PreDelete
InitializeCollection PreInsert
Load PreLoad
Lock PreUpdate
Merge Refresh
Persist Replicate
PostDelete SaveOrUpdate

Por cada tipo de evento existe una interfaz, de la forma eventoEventListener
y una clase base de Hibernate de la forma eventoEvent.
Tanto las interfaces como las clases se encuentran dentro del paquete
«org.hibernate.event».

El último paso consiste en asignar el oyente que
hemos programado al evento PostLoad, para que se ejecute justo
después de cargar las entidades. En nuestro caso sólo
existe una entidad, pero un oyente escuchará un evento
determinado independientemente de la entidad sobre la que ocurra el
mismo. Por tanto debemos ser cuidadosos al utilizar nuestro oyente,
asegurándonos de que el evento haya sido producido por la
entidad que creemos.

Para configurar nuestro oyente deberemos añadir las
siguientes líneas al fichero de configuración de
hibernate, dentro de la etiqueta <session-factory>.

Si volvemos a ejecutar la clase que muestra el listado, esta
vez obtendremos el resultado esperado:

Listado de usuarios con edades correctas

Esta vez el oyente se ha ejecutado justo después de
que se carguen los datos de cada usuario, actualizando el campo edad de
los mismos.

5. Dos mejor que uno

¿Y qué pasa si queremos tener varios oyentes
para un mismo evento? Simplemente tendremos que añadir el
oyente a la pila de oyentes en el fichero de configuración de
hibernate. Todos los oyentes serán llamados en su orden de
aparición; por esta razón es aconsejable mantener
siempre al final de la lista el oyente predeterminado de Hibernate, que
podría realizar acciones adicionales.

El fichero de configuración quedaría ahora
de la siguiente manera:

Y, por supuesto, deberemos añadir nuestra clase
oyente:

Este nuevo oyente aplicará un «lifting» a los
usuarios, rejuveneciéndoles 3 años
(¡qué maravilla!). Si ejecutamos de nuevo el listado
observaremos cómo ha descendido la media de edad de los
usuarios.

Listado con usuarios rejuvenecidos 3 años

6. Conclusiones

A la vista de los resultados de este tutorial podemos extraer
algunas conclusiones:

  • El uso de oyentes nos permite realizar acciones asociadas a
    la persistencia de nuestros objetos de manera automática y
    transparente a nuestra lógica de negocio. Esto nos permite
    realizar acciones que de otra manera tendríamos que controlar
    manualmente cada vez que hiciésemos una llamada a la Session
    de Hibernate.
  • Podemos asignar varios oyentes por cada evento para que
    realizen diferentes tareas y añadir o quitar oyentes
    de manera sencilla por medio del fichero de configuración de
    Hibernate.
  • Deberemos implementar una clase por cada oyente que
    necesitemos. Estas clases deben implementar la interfaz correspondiente
    y distinguir en su código de alguna manera la entidad sobre la
    que se está produciendo el evento.

Ya hemos visto el poder que tienen los eventos para realizar
acciones asociadas con la persistencia y alterar los valores de los
campos de nuestras entidades. No obstante puede resultar un poco
complicado tener que implementar una clase por cada oyente si
simplemente lo que queremos es ejecutar un método de la
entidad que realice ciertas operaciones sobre sus campos. ¿No
sería más sencillo poner simplemente
una anotación en el método que queramos
ejecutar al producirse un evento?  Responderemos a esta y
otras preguntas en la segunda parte de este tutorial.

Y eso es todo. En Autentia siempre estamos buscando soluciones
para los problemas que encontramos en nuestro trabajo cotidiano, y
esperamos que este y otros de nuestros tutoriales os ayuden
también a vosotros a solucionar problemas similares.

Dejar respuesta

Please enter your comment!
Please enter your name here