sábado, 30 de junio de 2012

Auditoría con JPA

Auditoría es uno de los pedidos que más suena cuando tenemos una base de datos.  Los requerimientos de auditoría pueden ser bien simples (como agregar cuatro columnas a todos los registros que indiquen usuario de creación, fecha de creación, usuario de modificación y fecha de modificación) o bien complejos (como clonar absolutamente todos los datos con cada modificación de un registro en tablas de historiales).

Para esto, la especificación de JPA provee anotaciones para marcar ciertos métodos que queremos que se invoquen dado determinado evento. Los eventos pueden ser:
  • @PostLoad
  • @PrePersist
  • @PostPersist
  • @PreUpdate
  • @PostUpdate
  • @PreRemove
  • @PostRemove
Podemos leer más sobre los eventos de JPA aquí.

Este link de la documentación de EclipseLink es también muy interesante. Explica distintas formas de auditar utilizando EclipseLink, la implementación de referencia de JPA 2. La que más me ha gustado a mí es la de la clase AuditedObject, que muestro a continuación:


La idea es bien simple. Todas las entidades que extiendan de AuditedObject van a heredar los atributos auditUser y auditTimestamp. Mediante el método updateAuditInfo que es disparado por los eventos @PrePersist y @PreUpdate, estos atributos se mantendrán actualizados de forma transparente. Lo único que tiene de malo es que hay que acordarse de setear el currentUser en la variable ThreadLocal. En una aplicación web esto tiene que hacerse en cada request. Yo, por ejemplo, resolví esto de forma sencilla usando un Filter de Servlets.

Cuando los requerimientos de auditoría son mucho más complejos, como en el caso de mantener tablas de historiales y repetir cada una de las columnas cada vez que hay un cambio sobre un registro, quizá necesitemos una solución más compleja como la que provee JBoss Envers para Hibernate.