JPA/SpringDataJPA

[SpringDataJPA] Auditing

걸어가는 신사 2022. 6. 4. 16:50
  • 엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶으면?
    • 등록일
    • 수정일
    • 등록자
    • 수정자

 

순수 JPA 사용

등록일, 수정일 적용

@MappedSuperclass
@Getter
public class JpaBaseEntity {

    @Column(updatable = false)
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;
    
    @PrePersist
    public void prePersist() {
        LocalDateTime now = LocalDateTime.now();
        createdDate = now;
        updatedDate = now;
    }
    
    @PreUpdate
    public void preUpdate() {
        updatedDate = LocalDateTime.now();
    }
}
  • @PrePersist
    • 해당 엔티티를 저장하기 이전 이벤트가 호출된다.
  • @PreUpdate
    • 해당 엔티티를 업데이트한 이전 이벤트가 호출된다. 

 

스프링 데이터 JPA 사용

1. 설정

(1) @EnableJpaAuditing ⇒ 스프링 부트 설정 클래스에 적용해야 한다.

@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataJpaApplication.class, args);
    }

}
  • Spring Boot main 메서드가 선언된 Class 또는 Configuration 클래스에 @EnableJpaAudting 어노테이션을 선언해야 한다. 

(2) @EntityListeners(AuditingEntityListener.class) ⇒ 엔티티에 적용

@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
	...
}
  • 엔티티 Class에 @EntityListeners(AuditingEntityListener.class) 어노테이션을 선언해야 한다. 

2. 사용 어노테이션

  • @CreatedDate : 등록일
  • @LastModifiedDate : 수정일
  • @CreatedBy : 등록자
  • @LastModifiedBy : 수정자

3. 스프링 데이터 Auditing 적용 - 등록일, 수정일, 등록자, 수정자

 

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public class BaseEntity {
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;
    
    @LastModifiedDate
    private LocalDateTime lastModifiedDate;
    
    @CreatedBy
    @Column(updatable = false)
    private String createdBy;
    
    @LastModifiedBy
    private String lastModifiedBy;
}

4. 등록자, 수정자를 처리해주는 AuditorAware 스프링 빈 등록

@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {

    public static void main(String[] args) {
        SpringApplication.run(DataJpaApplication.class, args);
    }

    @Bean
    public AuditorAware<String> auditorProvider() {
        // SpringSecurityContext 에서 session 정보를 확인한다.
        return () -> Optional.of(UUID.randomUUID().toString());
    }
}
  • 실무에서는 세션 정보나, 스프링 시큐리티 로그인 정보에서 ID를 받는다.

 

등록일, 수정일, 등록자, 수정자 분리

1. 분리의 필요성

  • 실무에서 대부분의 엔티티는 등록시간, 수정시간이 필요하지만, 등록자, 수정자는 없을 수도 있다.
  • Base 타입을 분리하고, 원하는 타입을 선택해서 상속한다.

2. 적용

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseTimeEntity {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;

}
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity extends BaseTimeEntity{

    @CreatedBy
    @Column(updatable = false)
    private String createdBy;

    @LastModifiedBy
    private String lastModifiedBy;

}
  • 등록일, 수정일을 필드로 가지는 BaseTimeEntity
  • BaseTimeEntity를 상속받고 등록자, 수정자 필드를 가지는 BaseEntity로 분리해주었다.

 

참고 : 저장시점에 등록자, 등록일 수정일, 수정자 모두 같은 데이터가 저장된다.
데이터가 중복 저장되는 것 같지만, 이렇게 해두면 변경 컬럼만 확인해도 마지막에 업데이트한 유저를 확인할 수 있으므로 유지보수 관점에서 편리하다. 이렇게 하지 않으면 변경 컬럼이 null 일 때 등록 컬럼을 또 찾아야 한다.
참고로 저장시점에 저장 데이터만 입력하고 싶으면 @EnableJpaAuditing(modifyOnCreate = false) 옵션을 사용하면 된다.
반응형