Eventos en Hibernate (parte III)

0
10377

Eventos en Hibernate (Parte III)

Índice de contenidos

  1. Introducción

  2. Entorno

  3. Un nuevo modelo

  4. Un DAO nuevo

  5. Configuración de Hibernate

  6. Un oyente muy atento

  7. Probar la aplicación

  8. Conclusiones

1. Introducción

Este tutorial es la tercera y última parte de la saga de
tutoriales sobre eventos en Hibernate. Si en la
primera parte vimos
cómo utilizar los oyentes de la SessionFactory y en la
segunda parte
utilizamos un EntityManager para poder utilizar las anotaciones de
EJB3, esta vez vamos a ver cómo combinar ambas cosas para
obtener lo mejor de dos mundos… Utilizaremos un oyente dentro de una
SessionFactory, que lo que hará será buscar anotaciones
EJB3 en los métodos de la entidad y sus superclases. En caso de
encontrarlas, ejecutará el método correspondiente.

Para nuestro ejemplo vamos a utilizar sólamente la anotación @PostLoad,
pero podríamos extenderlo fácilmente para cualquier
anotación y definir nuestros propios oyentes, de forma que una
vez definidos estos oyentes… ¡sólamente tendremos que
usar anotaciones para asociar métodos a los eventos, como
hacíamos con el EntityManager!.

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. Un nuevo modelo

Partiremos del proyecto que
creamos en el primer tutorial, pero vamos a definir un nuevo modelo de
datos que utilice herencia. Crearemos una clase Transporte y dos
subclases que hereden de la misma.

Aquí está el código de la clase Transporte:

Fijaros que hemos anotado el método «repostar»
con @PostLoad.
Además este método es privado, para comprobar que el
oyente pueda ejecutarlo sin importar su accesibilidad, utilizando
reflexión.

Y aquí tenemos TransporteTerrestre:

Aquí hemos anotado el método «derrapar».

Y, por último, TransporteAereo:

Esta
vez no hemos anotado ningún método a propósito,
para que nuestro oyente llame al método anotado en la clase
padre.

4. Un DAO nuevo

El Dao que habíamos utilizado en el ejemplo anterior
tampoco nos
vale ahora, porque hemos cambiado el modelo. No obstante las diferencias van a ser mínimas.

5. Configuración de Hibernate

Ahora
vamos a ver cómo quedaría el fichero de
configuración de Hibernate, que utiliza el nuevo modelo de
clases.

Como
se puede observar, hemos añadido el
oyente AnotacionPostLoadOyente para el evento PostLoad. Ya
sólo nos falta implementar el oyente y podremos probar nuestra
aplicación.

6. Un oyente muy atento

Nuestro oyente
utilizará reflexión para buscar anotaciones @PostLoad en
los métodos de la entidad que lo ha provocado y en sus
superclases hasta llegar a Object. Si encuentra un método
anotado, la búsqueda se detendrá y se ejecutará el
método. Además, la clase utiliza un Map
en el que irá guardando los métodos asociados a cada
clase sobre la que busque, de manera que no tenga que repetir una y
otra vez las búsquedas para una misma
clase.

¡OJO! El hecho de que utilicemos un Map para
guardar cierto estado sobre las búsquedas anteriores, hace que
está función NO SEA THREADSAFE por lo que NO ES RECOMENDABLE UTILIZARLA EN UN ENTORNO DE PRODUCCIÓN tal cual está.

Con este oyente estaremos simulando la funcionalidad que
nos ofrecen los oyentes del EntityManager, pero sólamente
utilizando una SessionFactory, lo cual es una buena idea en algunos
casos. Lástima que no se me haya ocurrido a mí 😉

Aquí tenemos el código de nuestro atentísimo oyente:

La clase auxiliar «buscarMetodoAnotadoRecursivo» es una función recursiva que comprueba
si la clase se ha buscado anteriormente o no. En el primer caso
devuelve directamente el metodo a ejecutar (o una referencia a metodoNulo si no hay ninguno).

En caso de que la clase no se haya buscado anteriormente
comprueba que no se trata de la clase Object (a la cual se
llegará si no se encuentra ningún método anotado)
y busca la anotación en todos los métodos de la clase. Si
encuentra el método detiene la búsqueda, pero en caso
contrario repite el proceso para la clase padre, y así
recursivamente, hasta encontrar el método o llegar a Object.

En cualquier caso, si el método no estaba ya guardado se guardará en el mapa para no tener que repetir búsquedas para las mismas clases en el futuro.

7. Probar la aplicación

Ahora sólamente nos queda probar la
aplicación que hemos rehecho por tercera vez, para ver si funciona como es
debido. Para ello modificamos nuestras dos clases de prueba para que
utilicen el nuevo modelo de datos.

Aquí está el código modificado de
nuestra
clase PruebaInsercion, que guardará en la base de datos dos transportes de cada tipo.

Y aquí tenemos la clase PruebaListado, que utiliza
también el nuevo Dao.

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

Listado de transportes en la base de datos

Ahora ejecutamos la prueba de listado y… ¡A la tercera va la
vencida! Esta vez nuestro oyente sí que estaba escuchando.

Salida por consola

Para
la primera clase de tipo transporte se ha realizado la búsqueda
de anotaciones y se ha ejecutado el método «repostar». Para la
segunda, como ya se había buscado anteriormente, se ha ejecutado
el método directamente.

Lo mismo ocurre para el transporte terrestre, aunque esta vez el método encontrado es «derrapar».

Para
el transporte aéreo se ha realizado inicialmente la
búsqueda y, como no habíamos anotado ningún
método de la clase, se ha utilizado el método «repostar»
de la clase padre, el cual ya estaba guardado en el mapa. La segunda
vez no ha sido necesario tampoco repetir la búsqueda para
TransporteAereo.

10. Conclusiones

A la vista de los resultados de este tutorial, podemos extraer
las siguientes conclusiones:

  • Con esta técnica podemos construir unos oyentes
    predeterminados para cualquier SessionFactory y después utilizar
    sólamente anotaciones para definir nuestros métodos de
    retrollamada.

  • Con un poco de imaginación y pericia casi siempre podemos
    encontrar una buena solución para resolver nuestros problemas.

Y esto es todo. Aquí termina nuestra serie de tutoriales
sobre eventos en Hibernate. Espero que os guste tanto seguirla como a
mí haberla hecho.

Dejar respuesta

Please enter your comment!
Please enter your name here