Al acceder a bases de datos, en ocasiones es importante determinar quién realizó un cambio en una entidad y cuándo. El registro de estos metadatos se llama revisión de cuentas.
Jakarta Persistence conoce a @EntityListeners, por ejemplo. Esto se puede utilizar para agregar información antes de escribir una entidad, por ejemplo, para el último acceso. Por supuesto, podríamos implementar la auditoría de esta manera manualmente, pero existen mejores enfoques.
Primavera Los datos admiten una auditoría sencilla y lista para usar. Además, esto no es específico de Spring Data JPA, sino que también es compatible con otros miembros de la familia Spring Data, incluido MongoDB.
Para la auditoría, los metadatos deben escribirse en columnas y campos. Hay dos formas de marcar estos lugares:
Veamos cómo se puede utilizar la auditoría en el caso de Spring Data JPA.
Primero, debe configurar @EnableJpaAuditing en una configuración, como @SpringBootApplication:
@SpringBootApplication
@EnableJpaAuditing
public class Data4uApplication { … }
7
Si se utiliza Jakarta Persistence, la implementación funciona a través de un oyente de entidad predefinido AuditingEntityListener. La tarea de AuditingEntityListener es observar los atributos persistentes, averiguar si están anotados y, de ser así, actualizarlos o configurarlos en consecuencia.
Un oyente de entidad se configura a través de @EntityListeners:
@Entity
@EntityListeners( AuditingEntityListener.class )
class Photo …
La entidad, cuando usa anotaciones, obtiene los atributos persistentes asignados con @CreatedBy, @LastModifiedBy, @CreatedDate o @LastModifiedDate. He aquí un ejemplo:
@Column( nullable = false, updatable = false )
@CreatedDate
private LocalDateTime created;
@Column( nullable = false )
@LastModifiedDate
private LocalDateTime updatedAt;
La auditoría de Spring Data permite registrar el tiempo de creación y modificación de entidades en atributos persistentes. La columna @CreatedDate siempre está ocupada y, por lo tanto, no admite valores NULL. Durante una actualización, no es necesario actualizar la columna @CreatedDate porque solo se escribe una vez durante la inserción. Por otro lado, la columna @LastModifiedDate se escribirá varias veces durante el ciclo de vida y, por lo tanto, no puede ser nula. Por lo tanto, configurar updatetable = false para la columna @LastModifiedDate sería falso.
De los cuatro tipos de anotaciones (@CreatedBy, @LastModifiedBy, @CreatedDate, @LastModifiedDate), dos tienen el componente «Fecha», que indica que se escribe una marca de tiempo. Los otros dos tipos de anotaciones contienen «Por», que es donde se escribe un identificador de usuario. Sin embargo, la pregunta es, ¿cómo obtiene el marco el identificador de usuario actual?
De forma predeterminada, Spring no puede determinar automáticamente un identificador de usuario; tenemos que ayudar. Para utilizar @CreatedBy y @LastModifiedBy, un componente de tipo AuditorAware
public interface AuditorAware<T> {
Optional<T> getCurrentAuditor();
}
Ahora veamos dos ejemplos de cómo se puede crear un bean de tipo AuditorAware administrado por Spring:
El nombre de usuario se toma de la propiedad del sistema:
@Bean
AuditorAware<String> systemUserNameAuditorAware( Environment env ) {
return () -> Optional.ofNullable( env.getProperty( "user.name" ) );
}
La primera implementación obtiene el nombre de usuario de las propiedades del sistema. En un servidor, esto tiene poco sentido porque un nombre de usuario no dependería del usuario que inició sesión.
El nombre de usuario se toma de SecurityContextHolder:
@Bean
AuditorAware<String> securityContextHolderAuditorAware() {
return () -> Optional.ofNullable(
SecurityContextHolder.getContext().getAuthentication().getName()
);
}
La segunda variante usa SecurityContext, desde el cual puede obtener un objeto de autenticación que devuelve un nombre mediante el método getName(). Sin embargo, es un requisito previo que una aplicación utilice Seguridad de primavera; de lo contrario, los tipos de datos no estarán disponibles.
La auditoría de Spring Data tiene dos limitaciones importantes que pueden no ser adecuadas para fines de auditoría reales. En primer lugar, no proporciona ninguna información sobre quién realizó modificaciones específicas, qué se cambió exactamente y en qué momento. Aunque los metadatos sobre el usuario que inició sesión y la marca de tiempo están disponibles, no ofrecen suficientes detalles sobre los cambios realizados. En segundo lugar, los metadatos sobre usuarios y horarios se almacenan junto con la entidad. Por lo tanto, si se eliminan datos, se pierde toda la información.
Aunque el enfoque de auditoría de Spring Data es suficiente para mostrar información como cuándo se creó o modificó por última vez una página, puede no ser adecuado para requisitos de auditoría reales. Afortunadamente, existen enfoques alternativos como el Hibernar Envers proyecto (https://hibernate.org/orm/envers/), que aborda estas limitaciones mediante el uso de tablas adicionales para almacenar los datos modificados.
7
El proyecto Envers de datos de primavera integra Hibernate Envers en Spring Framework. El proceso es sencillo: debe configurar la anotación @Audited en el bean de entidad y el resto se hace automáticamente. Hibernate Envers creará nuevas tablas y registrará quién cambió qué fila y cuándo, lo que incluye el historial completo de todos los cambios. Si algún atributo persistente no debe registrarse, se puede anotar con @NotAudited.
Sin embargo, el hecho de que Hibernate Envers escriba todos los cambios en las tablas no es el único beneficio. También hay un repositorio de revisiones que se puede utilizar para consultar y realizar un seguimiento de los cambios realizados. Esta es una característica esencial para fines de auditoría, ya que proporciona un historial completo de todos los cambios realizados en las entidades. Para obtener información detallada, se recomienda consultar la documentación de referencia del sitio de Hibernate.
Nota: Cuando todos los cambios en las filas se gestionan en el lado del software, los costos pueden aumentar significativamente porque cada modificación activa automáticamente una copia de seguridad de los datos en las tablas de revisión en segundo plano. Los sistemas de gestión de bases de datos profesionales suelen proporcionar capacidades de auditoría nativas, lo que puede hacer que el proceso de auditoría sea más eficiente porque el código y las tablas están estrechamente integrados con el sistema de gestión de bases de datos. Sin embargo, Hibernate Envers tiene una ventaja notable en términos de portabilidad porque puede funcionar con cualquier RDBMS. Esto significa que no está vinculado a un sistema de gestión de bases de datos específico y se puede utilizar en múltiples plataformas, lo que la convierte en una solución de auditoría flexible y adaptable.
Nota del editor: esta publicación ha sido adaptada de una sección del libro. Spring Boot 3 y Spring Framework 6 Por Christian Ullenboom.
Calle Eloy Gonzalo, 27
Madrid, Madrid.
Código Postal 28010
Paseo de la Reforma 26
Colonia Juárez, Cuauhtémoc
Ciudad de México 06600
Real Cariari
Autopista General Cañas,
San José, SJ 40104
Av. Jorge Basadre 349
San Isidro
Lima, LIM 15073