Provisional_hibernate_dia5

Page 1

Interceptores y filtros Octubre 2010

JosĂŠ A. GarcĂ­a jagarcia@siteframe.tk


Interceptores Los interceptores nos proporcionan llamadas, a nivel sesión que permiten a la aplicación inspeccionar y/o manipular propiedades de un objeto persistente antes de ser guardado, actualizado, eliminado, o cargado dentro de nuestro contexto persistente. Pueden ser utilizados para monitorear los eventos ocurridos o para sobreescribir la funcionalidad de un módulo. El ejemplo clásico es la auditoría del sistema, para realizar un log de eventos que indiquen los cambios que realizan sobre nuestras entidades. 2


Interceptores La forma más "directa" de crear un interceptor es implementar la interface "org.hibernate.Interceptor" la cual tiene nada más y nada menos que 18 métodos. La siguiente tabla muestra una breve descripción de los 10 métodos más importantes de esta interface:

3


Interceptores

4


Interceptores

5


Interceptores Como podemos ver, esta interface tiene métodos para prácticamente cualquier cosa que se nos pueda ofrecer. Sin embargo, como sabemos, si queremos implementar una interface entonces debemos proporcionar la implementación de cada uno de los métodos que tiene la interface (y con 18 métodos esto no es una tarea nada fácil). Afortunadamente los creadores de Hibernate nos ofrecen una manera de no tener que implementar, por nosotros mismos, cada uno de estos métodos, a través de la clase "org.hibernate.EmptyInterceptor" 6


Interceptores. Ejemplo Consideremos el ejemplo del sistema de auditoría: Consideramos como críticos los módulos de creación y eliminación de usuarios de nuestra aplicación y por ello implementamos un sistema de auditorias que deberá tener los siguientes requisitos:

1. Cada vez que un Usuario sea almacenado se debe mostrar un mensaje en consola. 2. Cada vez que un Usuario sea eliminado se debe mostrar un mensaje en consola.

7


Interceptores. Ejemplo Si revisamos la lista de métodos de la interface "Interceptor" vemos que tiene 2 que podrían servirnos: "onSave" para el requerimiento número 1, y "onDelete" para el requerimiento número 2. Por lo que sobreescribimos estos dos métodos en una clase "InterceptorAuditoria".

8


Interceptores. Ejemplo

9


Interceptores. Ejemplo

Dentro de la lista de parámetros que recibe este método solamente nos interesa uno "entity" que es la entidad que será almacenada en nuestra base de datos. Para poder saber si estamos guardando un "Usuario" o algún otro tipo de entidad debemos usar el operador "instanceof". Después haremos un cast al tipo "Usuario" para poder obtener de este su 10 "nombre" y su "username“.


Interceptores. Ejemplo

Recordemos que, segĂşn la lista, "onDelete" es llamado antes de que la entidad sea eliminada. Podemos ver en la firma del mĂŠtodo que, a diferencia de "onSave", "onDelete" no regresa nada. Esto es debido a que como la entidad va a ser eliminada, no tiene sentido modificar los atributos del objeto. 11


Interceptores. Ejemplo

Dentro de los parĂĄmetros que recibe el mĂŠtodo, ahora hay 2 que nos interesan: "entity", que es la entidad que se va a eliminar, e "id", que es el identificador de dicha entidad en la base de datos.

12


Interceptores. Ejemplo

Nuevamente, dentro del método "onDelete" usaremos el operador "instanceof" para determinar si estamos eliminando un "Usuario". Después haremos un cast al tipo "Usuario" para poder obtener de este su "nombre" y usaremos el argumento "id" para mostrar el identificador de esta entidad (el cual también podríamos obtener invocando al método 13 "getId()" de nuestro Usuario)


Interceptores. Tipos. Ya teniendo listo nuestro interceptor, lo siguiente que debemos hacer es indicarle a Hibernate que este interceptor existe para que pueda utilizarlo. Este es el momento indicado para decir que Hibernate maneja dos tipos de Interceptores: * Interceptores de Session (Session-scoped) * Interceptores de SessionFactory (SessionFactory-scoped)

Los interceptores de session son especificados cuando se abre una sesión, usando el método "openSession" de "SessionFactory" (que en nuestra clase "AbstracDAO" ocurre en el método "iniciaOperacion"), y funcionan únicamente para la sesión que se está abriendo.

14


Interceptores. Tipos.

Los interceptores de SessionFactory se registran con el objeto "org.hibernate.cfg.Configuration" que usamos para construir la "SessionFactory", usando el método buildSessionFactory" (que en nuestra clase "HibernateUtil" ocurre en el constructor estático).

Estos interceptores son usados en todas las sesiones que se abran en nuestra aplicación (a menos que especifiquemos interceptores para una sesión específica usando los interceptores de session).

15


Interceptores. Ejemplo

MOSTRAR EJEMPLO HIBERNATE_INTERCEPTORES

16


Eventos

Si queremos que nuestra aplicación reaccione a ciertos eventos de nuestra capa de persistencia, podemos usar la arquitectura de eventos de Hibernate. El sistema de eventos puede ser usado para complementar, o reemplazar, el uso de interceptores. Todos los métodos de la interface "Session" están relacionados con un evento del cual podemos recibir una notificación. Cuando invocamos algún método como "save", "load", "delete", etc.

17


Eventos. Funcionamiento

Hibernate lanza un evento y podemos realizar alguna acci贸n en ese momento. Por cada tipo de evento existe una interface "xxEventListener" que tendremos que implementar para recibir notificaciones para ese evento. Estas interfaces reciben un par谩metro del tipo del evento que la lanzo.

18


Eventos. Ejemplo

Por ejemplo, si esperamos una notificaci贸n de un evento "saveOrUpdate", tendremos que implementar una interface "org.hibernate.event.SaveOrUpdateEventListener" en cuyo m茅todo de escucha recibe un objeto de tipo "org.hibernate.event.SaveOrUpdateEvent".

19


Eventos. Tipos de Eventos

El paquete "org.hibernate.event" contiene las siguientes interfaces que nos permiten recibir notificaciones de eventos: AutoFlushEventListener DeleteEventListener DirtyCheckEventListener FlushEntityEventListener InitializeCollectionEventListener LoadEventListener LockEventListener MergeEventListener PersistEventListener PostCollectionRecreateEventListener PostCollectionRemoveEventListener PostCollectionUpdateEventListener 20


Eventos. Tipos de Eventos (Cont..)

El paquete "org.hibernate.event" contiene las siguientes interfaces que nos permiten recibir notificaciones de eventos: PostDeleteEventListener PostInsertEventListener PostLoadEventListener PostUpdateEventListener PreCollectionRecreateEventListener PreCollectionRemoveEventListener PreCollectionUpdateEventListener PreDeleteEventListener PreInsertEventListener PreLoadEventListener PreUpdateEventListener RefreshEventListener ReplicateEventListener SaveOrUpdateEventListener

21


Eventos. Ejemplo

Consideremos ahora nuevos requisitos para nuestro ejemplo: 1. Antes de que un Usuario sea cargado debemos mostrar un mensaje en consola. 2. Antes de eliminar un Usuario debemos mostrar un mensaje en consola. 3. DespuĂŠs de eliminar un Usuario debemos mostrar un mensaje en consola. 4. Antes de actualizar un Usuario debemos mostrar un mensaje en consola.

22


Eventos. Ejemplo

Comencemos viendo c贸mo cubrir el primer requerimiento. Si revisamos la lista de listeners disponibles vemos que hay uno llamado "PostLoadEventListener" el cual, como su nombre lo indica, es llamado despu茅s de que la entidad es cargada en el contexto persistente de nuestra aplicaci贸n. Como la entidad ya se encuentra cargada, es posible acceder a sus atributos para consultarlos o modificarlos.

23


Eventos. Ejemplo

Creamos una nueva clase, en el paquete "eventos", llamada "CargaUsuarioListener", la cual implementarĂĄ la interface "PostLoadEventListener": public class CargaUsuarioListener implements PostLoadEventListener { } La interface "PostLoadEventListener" tiene un solo mĂŠtodo llamado "onPostLoad", el cual recibe un solo argumento de tipo "org.hibernate.event.PostLoadEvent", de la siguiente forma: public void onPostLoad(PostLoadEvent postLoadEvent); 24


Eventos. Ejemplo

25


Eventos. Ejemplo

Veamos ahora el segundo requerimiento: "Antes de eliminar un Usuario debemos mostrar un mensaje en consola".

Nuevamente si revisamos la lista de listeners vemos que existe una interface llamada "PreDeleteEventListener" que, como su nombre indica, es llamado antes de que una entidad sea eliminada de la base de datos.

26


Eventos. Ejemplo La interface "PreDeleteEventListener" tiene un solo método llamado "onPreDelete", que regresa un booleano que indica la operación de eliminación debe ser cancelada. También recibe un único argumento de tipo "org.hibernate.event.PreDeleteEvent".


Eventos. Ejemplo Prosigamos con el tercer requerimiento: "DespuĂŠs de eliminar un Usuario debemos mostrar un mensaje en consola". Para este requerimiento nuevamente haremos uso de una de las interfaces de la lista: "PostDeleteEventListener", asĂ­ que crearemos una nueva clase llamada "PostEliminaUsuarioListener", en el paquete "eventos", que implemente esta interface.


Eventos. Ejemplo


Eventos. Declaración

Ahora debemos decirle a Hibernate que queremos que estas clases reciban notificaciones para los eventos indicados.

Para esto existen dos formas: la primera y que me parece más sencilla es colocando los listeners en el archivo de configuración "hibernate.cfg.xml" en la configuración del "session-factory", y la segunda es en código, al momento de crear el objeto "org.hibernate.cfg.Configuration" o "org.hibernate.cfg.AnnotationConfiguration" (que nosotros hacemos en la clase "HibernateUtil" en nuestro bloque de inicialización estático).


Eventos. Declaraciรณn en XML

En la primera de las formas debemos colocar, al final del archivo "hibernate.cfg.xml", un elemento "<event>", en cuyo atributo "type" indicamos el tipo de evento que estรก esperando recibir el listener que indicaremos posteriormente en el sub-elemento "<listener>", en cuyo atributo "class" indicaremos la clase que responderรก al evento.


Eventos. Declaraci贸n en XML


Eventos. Declaraci贸n en XML


Eventos. Declaraci贸n en XML


Eventos. Declaraci贸n en XML


Eventos. Ejemplo

MOSTRAR EJEMPLO HIBERNATE_EVENTOS

36


Ejercicio. El empresario tramposo

Imaginemos un supuesto en el que regentamos una empresa un poco deshonesta. En nuestra empresa trabajan dos tipos de empleados. Los empleados prescindibles y los imprescindibles. De estos últimos además existen algunos que por tener relaciones de parentesco queremos tratar de forma especial. La gestión del personal y sus nóminas se realiza a través de una única aplicación a la cual tenemos acceso y que realiza persistencia utilizando hibernate. Queremos modificar dicha aplicación para que alterando el código el mínimo imprescindible seamos capaces de:

37


Ejercicio. El empresario tramposo

1. Interceptar la inserci贸n de un empleado, acceder a su salario y descontarle un 30% si se trata de un empleado prescindible, un 10% si es imprescindible, y nada si tiene trato preferente. 2. Interceptar las actualizaciones de empleados que afecten a su n贸mina y deshacer los cambios si se trata de un empleado prescindible.

38


Turn static files into dynamic content formats.

Create a flipbook
Issuu converts static files into: digital portfolios, online yearbooks, online catalogs, digital photo albums and more. Sign up and create your flipbook.