sábado, 8 de octubre de 2016

Como realizar la Auditoria de BBDD con Spring Data y Spring Boot


Una tarea recurrente en el mundo del Backend a nivel de BBDD, es que las tablas tengan campos de auditoria (quien ha creado o editado el registro, y cuando). Y otra tarea recuerrente es obtener los datos del usuario para hacer registrar sus datos en los insert o updates. 

Gracias a Spring Data podremos hacerlo con poco más que una anotación. Y a continuación te indicaré como realizarlo con Spring Boot. 

Supongamos que cada tabla tiene los capos 'CREATE_USER', 'MODIFY_USER', 'CREATE_DATE' y 'MODIFY_DATE' (que nos permiten lo anteriormente comentado). Estos campos los crearemos en una clase de la cual extenderán el resto de clases JPA (con idea de reducir código). Y tendran unas etiquetas específicas asociadas '@CreatedBy', '@LastModifiedBy', '@CreatedDate' y '@LastModifiedDate'.Esta será la clase:

@MappedSuperclass
public abstract class GenericEntity<K extends Serializable> implements Serializable {
 protected Date createDate;
 protected Date modifyDate;
 protected Integer createUser;
 protected Integer modifyUser;

 @Temporal( TemporalType.DATE )
 @Column( name = "CREATE_DATE" )
 @CreatedDate
 public Date getCreateDate() {
  return createDate;
 }

 @Temporal( TemporalType.DATE )
 @Column( name = "MODIFY_DATE" )
 @LastModifiedDate
 public Date getModifyDate() {
  return modifyDate;
 }

 @Column( name = "CREATE_USER" )
 @CreatedBy
 public String getCreateUser() {
  return createUser;
 }

 @Column( name = "MODIFY_USER" )
 @LastModifiedBy
 public String getModifyUser() {
  return modifyUser;
 }
}

Para que funcione las anotaciones, en el caso de los campos fecha no debemos hacer nada más. Pero para poder obtener  la información del  usuario deberemos hacer uso de la interfaz AuditorAware<T> (Siendo T el tipo de valor a insertar en los campos de 'CREATE_USER' y 'MODIFY_USER'). La clase que lo implemente, deberá obtener los datos de Spring Security y devolver el dato que deseamos almacenar en BBDD (el nombre del usuario, el identificador del mismo, etc).

@Component
public class MyOwnAuditorAware implements AuditorAware<String> {
 @Override
 public String getCurrentAuditor() {
  Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
  if( authentication == null || !authentication.isAuthenticated() ) {
   return null;
  }
  return ((CustomUserDetails) authentication.getPrincipal()).getUsername();
 }
}

El último paso será configurar en Spring Boot para que haga uso de el, Esto lo podemos hacer de la siguiente forma

@EnableJpaAuditing( auditorAwareRef = "myOwnAuditorAware" )
public class WebMvcConfig extends WebMvcConfigurerAdapter {

Y en la propia clase, con la anotación 'AuditingEntityListener', 

2 comentarios:

  1. La idea de esta aproximación es que las entidades JPA, extiendan de la clase GenericEntity. Y como sabes cada entidad JPA tiene que ser la representación de una tabla de BBDD. Por tanto estos atributos de la clase GenericEntity, deben ser a la vez, campos de BBDD.
    Por lo que una entidad JPA que extienda de GenericEntity debe tener los siguientes campos en la tabla de BBDD: CREATE_DATE, MODIFY_DATE, CREATE_USER y MODIFY_USER. Así que la respuesta a tu pregunta, sería que esa información se almacenaría en BBDD.

    ResponderEliminar