Purmarili Purmarili - 1 month ago 36
Java Question

Auditing Changes in Entity JPA

I have Spring MVC + JPA applications.
I have several entities in application which Are constantly changing. I want to be able to audit this changes. I found that there is an @audited annotation that track changes to certain fields or whole Entity. I want to know if there any way to configure this track options - I want to be able to track what was changed and who changed it.Also is it possible to have changes from several Entities in 1 Table in SQL? Also is it possible to track changes of - @OneToMany Fields in Entity?

Thanks

Answer

Yes, you can keep track the changes made, updated user and time-stamp.

Hibernate provides @Audited annotation to maintain entity version.

Spring provides @CreatedBy @LastModifiedBy @CreatedDate and @LastModifiedDate annotations, among these you need to provide the user name who updates using AuditorAware bean.

To enable auditing,

  1. should add @EnableJpaAuditing on configuration class
  2. @Audited and @EntityListeners(AuditingEntityListener.class) on entities
  3. AuditorAware<T> to provide the username
  4. Children entities should be annotated with @Audited

Example

@Bean
public AuditorAware<String> createAuditorProvider() {
    return () -> "username"; // should be from context/session
}

For each entities an additional table will be created to maintain version

  1. {ENTITY_NAME}_AUD // can override the prefix and suffix of audit table name
  2. REVINFO

below is an example of one-to-many relationship with hibernate and spring auditing

UserInfo.java

@Audited
@Entity
@EntityListeners(AuditingEntityListener.class)
public class UserInfo extends AuditInfo {

    @Id
    @GeneratedValue
    private Long id;

    @Column
    private String name;

    @OneToMany(mappedBy = "userInfo", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    private List<UserAddress> addresses;

}

UserAddress.java

@Entity
@Audited
@EntityListeners(AuditingEntityListener.class)
public class UserAddress extends AuditInfo {

    @Id
    @GeneratedValue
    private Long addressId;

    @ManyToOne
    @JoinColumn(name = "id", nullable = false)
    private UserInfo userInfo;

    @Column
    private Long no;

    @Column
    private String street;

}

AuditInfo.java

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditInfo {

    @CreatedBy
    private String createdBy;

    @LastModifiedBy
    private String updatedBy;

    @CreatedDate
    private LocalDateTime createdOn;

    @LastModifiedDate
    private LocalDateTime updatedOn;

}