Enrique Viñé Lerma

Consultor tecnológico de desarrollo de proyectos informáticos.

Ingeniero Técnico en Informática por la Universidad Politécnica de Madrid.

Puedes encontrarme en Autentia: Ofrecemos servicios de soporte a desarrollo, factoría y formación

Somos expertos en Java/J2EE

Ver todos los tutoriales del autor

Fecha de publicación del tutorial: 2009-01-28

Tutorial visitado 6.318 veces Descargar en PDF
Eventos en Hibernate

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.

A continuación puedes evaluarlo:

Regístrate para evaluarlo

Por favor, vota +1 o compártelo si te pareció interesante

Share |
Anímate y coméntanos lo que pienses sobre este TUTORIAL: