You don't have access to this class

Keep learning! Join and start boosting your career

Aprovecha el precio especial y haz tu profesión a prueba de IA

Antes: $249

Currency
$209
Suscríbete

Termina en:

0 Días
18 Hrs
39 Min
6 Seg

Crear listener personalizado para auditoría

23/25
Resources

How to audit entities using a custom listener?

Auditing a database is fundamental to maintain the integrity and control of the modifications in our entities. Today we are going to learn how to audit all the operations in our "PIXA" entity using a custom listener. This mechanism will not only monitor the creation or modification dates, but also any change in your data.

What is a custom listener?

A listener is a class with methods that react to entity lifecycle events. By creating a listener specific to our PIXA entity, we will be able to track events such as the creation, update or deletion of records.

How to implement the AuditPIXAListener?

  1. Create the audit package: Start by creating a new package called audit inside the persistence folder, where you can group all the necessary listeners.

  2. Define the AuditPIXAListener class: This class will manage the auditable events. It implements specific methods using annotations such as @PostPersist, @PostUpdate, and @PreRemove.

  3. Use of annotations for methods:

    • @PostPersist and @PostUpdate: Capture events when an entity is saved or updated.
      public void onPostPersist(PIXAEntity entity) { System.out.println("Entity: " + entity.toString());}
    • @PreRemove: executed before deleting a record.
      public void onPreRemove(PIXAEntity entity) { System.out.println("Preparing to remove: " + entity.toString());}
  4. Implement toString for PIXAEntity: Make sure that the PIXAEntity class has a toString method that includes all relevant data to facilitate visual auditing of previous and current data.

How to handle post load with cloning?

The postLoad method allows you to audit the values before a modification by loading the current state of the entity. For this:

  • Use SerializationUtils to clone the entity and avoid overwriting in memory.
    @PostLoadpublic void postLoad(PIXAEntity entity) { this.currentValue = SerializationUtils.clone(entity); System.out.println("Current state loaded.");}

What happens when inserting or modifying data?

When we modify a field, when we make a request, you will notice in the console how the system prints both the previous state and the new one:

  • We see the execution in the correct order: postLoad, update, and finally postPersist.
  • Example of audited values:
    "oldValue: motherboard, newValue: holymotherherd".

Final recommendations for auditing

It is important to always commit changes by verifying that the ID is consistent, especially in update operations. The results obtained can be sent to databases for historical records or even to log files.

Finally, remember that this type of auditing is effective when using Spring Data Repositories lifecycle methods such as save. For native queries, these processes will not be transparent.

Continue exploring ways to improve your entity management with Spring Data JPA, and don't forget to join me in the next class to discover how to execute stored procedures using this powerful tool. Keep learning and expanding your skills!

Contributions 5

Questions 4

Sort by:

Want to see more contributions, questions and answers from the community?

También se puede usar la anotación @ToString de lombok para no sobrescribir el método toString() en la clase, adicionalmente se pueden excluir campos de la salida:

import lombok.ToString;

@ToString
public class ToStringExample {
  private static final int STATIC_VAR = 10;
  private String name;
  private Shape shape = new Square(5, 10);
  private String[] tags;
  @ToString.Exclude private int id;
...
}

Luego de implementar el metodo toString() en la clase PizzaEntity, ya luego en la clase AuditPizzaListener no es necesario para las instancias de objeto entidad invocar explicitamente el metodo toString(), solo con imprimir el objeto directamente ya por default invoca el metodo toString(), entonces tando para insert, update o delete funciona.

Las anotaciones @PrePersist, @PreUpdate, @PreRemove, @PostPersist, @PostUpdate y @PostRemove que llevan los métodos se podrían asemejar a los Triggers de base de datos relaciones.

Aquí sería mejor cargar el valor anterior en el @PreUpdate, con eso se garantizaría que el valor en currentValue sea el correcto.

sorry, código Kotlin:

@PreUpdate
fun onPreUpdate(entity: PizzaEntity) {
    currentValue = entity.copy()
}