Fermer

mai 26, 2020

Audit avec Spring Data JPA


L'audit avec Hibernate Envers est une petite chose à implémenter mais est le moyen le plus simple pour auditer des données persistantes dans une application Spring Boot . Cependant, Envers est d'avis et peut ne pas répondre aux exigences d'audit des données pour votre organisation, telles que la conception ou le contenu du schéma de table d'audit.

Les applications Spring Boot qui nécessitent des capacités d'audit plus flexibles peuvent implémenter l'audit à l'aide de Spring Data JPA.

Approche d'audit

Cette approche implémente des rappels pour les événements du cycle de vie JPA. L'exemple d'implémentation résume le code commun et les données d'audit communes pour convenir aux applications qui fonctionnent avec de nombreuses entités:

  • Une classe d'écouteur pour chaque entité JPA encapsule les méthodes de rappel pour chaque opération CUD sur l'entité.
  • Chaque classe d'écouteur étend un résumé commun classe d'écoute.
  • Chaque entité enregistre sa classe d'écoute via une annotation Spring Data JPA.

La classe d'écoute abstraite

Le code commun aux rappels d'écoute d'entité est fourni par une classe d'écoute abstraite.

 abstract class AbstractEntityListener  {




void doCreate (entité E) {

postProcess (entité, «CREATE»);

}




void doUpdate (entité E) {

postProcess (entité, ”UPDATE”);

}




void doDelete (entité E) {

postProcess (entité, «DELETE»);

}




private void postProcess (entité E, action String) {

TransactionSynchronizationManager.registerSynchronization (

new TransactionSynchronizationAdapter () {

@Passer outre

public void afterCompletion (int status) {

if (status == STATUS_COMMITTED) {

persister (entité, action);

}

}

});

}




le vide privé persiste (entité E, action de chaîne) {

EntityManagerFactory entityManagerFactory =

AuditUtil.getBean (EntityManagerFactory.class);

EntityManager entityManager = entityManagerFactory.createEntityManager ();

AuditBase auditEntity = mapAuditEntity (entité);

auditEntity.setAuditAction (action);

auditEntity.setAuditDate (Instant.now ());




entityManager.getTransaction (). begin ();

entityManager.persist (auditEntity);

entityManager.flush ();

entityManager.getTransaction (). commit ();

entityManager.close ();

}




résumé AuditBase mapAuditEntity (entité E);




} 

REMARQUES:

  1. doCreate, doUpdate et doDelete fournissent des implémentations par défaut pour les rappels de cycle de vie sur chacune des opérations CUD de l'entité.
  2. La méthode postProcess utilise la synchronisation des transactions Spring pour un contrôle précis sur le moment où l'entité l'audit a lieu. Dans cet exemple, les données d'audit ne sont conservées qu'après la validation effective de la modification de l'entité correspondante.
  3. La méthode persist effectue le travail réel de persistance des données d'audit en créant un objet EntityManager et en l'utilisant pour effectuer le travail. [19659006] Chaque entité d'audit étend AuditBase, qui fournit des champs d'audit communs.
  4. Les écouteurs d'entité sont instanciés par JPA et donc l'injection de dépendance Spring n'est pas prise en charge dans une classe d'écouteur d'entité. La classe AuditUtil fournit le mécanisme permettant d'obtenir des beans Spring dans les écouteurs d'entité.

La ​​classe AuditUtil

 Covid 19

Cette classe implémente ApplicationContextAware et fournit la méthode getBean (), qui renvoie un bean Spring de la classe demandée. [19659010] @Component

public class AuditUtil implémente ApplicationContextAware {

contexte ApplicationContext statique privé;

@Passer outre

public void setApplicationContext (ApplicationContext applicationContext) {

setContext (applicationContext);

}

public statique T getBean (Classe beanClass) {

return context.getBean (beanClass);

}

vide statique fixe setContext (contexte ApplicationContext) {

AuditUtil.context = context;

}

}

La classe d'écoute d'entité

La classe d'écoute de chaque entité fournit les rappels JPA réels.

 La classe publique MyEntityListener étend AbstractEntityListener  {




@PostPersist

public void onCreate (entité MyEntity) {

// Mises à jour personnalisées sur l'entité modifiée, le cas échéant.

doCreate (entité);

}




@PostUpdate

public void onUpdate (entité MyEntity) {

// Mises à jour personnalisées sur l'entité modifiée, le cas échéant.

doUpdate (entité);

}




@PostRemove

public void onDelete (entité MyEntity) {

// Mises à jour personnalisées sur l'entité modifiée, le cas échéant.

doDelete (entité);

}




@Passer outre

public MyEntityAudit mapAuditEntity (entité MyEntity) {

// Remplit l'entité d'audit à partir des données de l'entité modifiée.

}




} 

REMARQUES:

  1. L'annotation sur chaque méthode CUD enregistre le rappel de cycle de vie avec JPA.
  2. La méthode mapAuditEntity fournit le code qui copie les données de l'entité dans l'entité d'audit correspondante. Les mappeurs tels que mapstuct ou modelMapper sont de bons choix lorsque les données d'audit correspondent étroitement aux données d'entité.

La ​​classe d'entité

Chaque classe d'entité est écrite à l'aide d'annotations JPA normales mais enregistre également sa classe d'écoute d'entité avec JPA.

 @Entity

@Table (name = "MY_ENTITY")

@EntityListeners (MyEntityListener.class)

Classe publique MyEntity {

…

} 

La classe d'audit d'entité

Une classe d'audit d'entité est écrite à l'aide d'annotations JPA normales et les données d'audit peuvent être personnalisées de manière à satisfaire les exigences d'audit des données de votre organisation. Dans cet exemple d'implémentation, chaque classe d'audit d'entité étend AuditBase, qui fournit des données d'audit communes.

 @Entity

@Table (name = “MY_ENTITY_AUDIT”)

public class MyEntityAudit étend AuditBase {

…

} 

La classe AuditBase

AuditBase fournit des données d'audit communes.

 @MappedSuperclass

classe abstraite publique AuditBase {

@Column (name = "AUDIT_ACTION")

auditAction chaîne privée;




@Column (name = "AUDITED_AT")

Private Instant auditedAt;




@Column (name = “CREATED_BY”)

private String createdBy;




@Column (name = “CREATED_AT”)

private Instant createdAt;




@Column (name = “UPDATED_BY”)

private String updatedBy;




@Column (name = “UPDATED_AT”)

private Instant updatedAt;

} 

Références:

https://www.baeldung.com/database-auditing-jpa

https://dev.to/ njnareshjoshi / jpa-auditing-persisting-audit-logs-automatically-using-entitylisteners-238p






Source link