노트

JPA Auditing

JPA Auditing

백엔드#jpa · 연결된 개념 5개

쉽게 말하면

JPA Auditing은 서류에 '작성: 누가 언제, 최종 수정: 누가 언제' 도장을 저장할 때마다 자동으로 찍어 주는 기능이에요. 엔티티마다 생성·수정 시각을 채우는 코드를 반복하지 않아도 되죠.

비유가 깨지는 곳 도장은 마지막 수정만 남겨서 무엇이 어떻게 바뀌었는지 이력은 없어요. 이력은 Envers나 CDC로 남기고, '누가'는 AuditorAware로 앱이 알려 줘야 해요. 벌크 UPDATE엔 도장이 안 찍혀요.

JPA Auditing은 엔티티의 생성·수정 시각과 생성자·수정자를 저장할 때 자동으로 채워 주는 Spring Data JPA 기능이다. 모든 엔티티에 반복되는 createdAt = now() 코드를 없앤다.

@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
@Getter
public abstract class BaseEntity {
    @CreatedDate @Column(updatable = false) private LocalDateTime createdAt;
    @LastModifiedDate                     private LocalDateTime updatedAt;
    @CreatedBy   @Column(updatable = false) private String createdBy;
    @LastModifiedBy                       private String updatedBy;
}
 
@Entity
public class Contact extends BaseEntity { ... }
@Configuration
@EnableJpaAuditing(auditorAwareRef = "auditorAware")
public class JpaConfig {
    @Bean
    AuditorAware<String> auditorAware() {
        return () -> Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication())
            .filter(Authentication::isAuthenticated)
            .map(Authentication::getName);
    }
}
  • @EnableJpaAuditing으로 켜고, 엔티티에 AuditingEntityListener를 등록한다
  • 시각은 자동으로 채워지지만, "누가"는 앱이 알려 줘야 한다. AuditorAware를 구현해 현재 로그인 사용자를 돌려준다(시큐리티 필터체인)
  • 공통 필드는 @MappedSuperclass 기반 클래스로 모은다. 테이블은 엔티티마다 따로 생긴다
  • 시각 컬럼은 저장 시점(@PrePersist·@PreUpdate)에 채워지므로, 벌크 UPDATE 쿼리에는 적용되지 않는다(JPQL과 @Query)

한계

Auditing은 "마지막으로 누가 언제 바꿨나"만 남긴다. 무엇이 어떻게 바뀌었는지 이력 전체가 필요하면 Hibernate Envers 같은 이력 테이블(audit table)이나, 변경을 이벤트로 남기는 방식(CDC (변경 데이터 캡처))을 쓴다. 장고에서는 auto_now_add·auto_now 필드 옵션이 시각 부분을 같은 방식으로 처리한다(Django 모델 매니저와 QuerySet).

출처: Spring Data JPA 문서: Auditing 애너테이션 · AuditorAware · JPA Auditing 설정

연결된 개념

이 노트를 가리키는 문서

뜻이 가까운 노트

  • 영속성 컨텍스트

    트랜잭션 동안 엔티티를 보관하고 변경을 추적하는 JPA의 작업 공간.

  • JPA 연관관계 매핑

    JPA(Jakarta Persistence, 옛 이름 Java Persistence API) 연관관계 매핑(association mapping)은 테이블의 외래키(foreign key) 관계를 엔티티 사이의 참조로 표현하는 방법이다. 핵심은 외래키를 관리하는 쪽(연관관계의 주인, owning side)을 정하는 것이고, 양방향 관계에서 반대쪽은 mappedBy로 "나는 읽기 전용 거울"이라고 표시한다.

  • 더티 체킹

    영속 상태 엔티티의 필드를 바꾸기만 하면, flush(영속성 컨텍스트의 변경을 DB에 반영) 시점에 처음 스냅샷(snapshot)과 비교해 바뀐 엔티티의 UPDATE를 만들어 보내는 기능. save()를 다시 부를 필요가 없다.

  • JDBC와 JdbcTemplate

    JDBC(Java Database Connectivity)는 자바가 여러 DB와 통신하기 위한 표준 API이고, Hibernate·MyBatis·스프링 JDBC 모두 그 위에 있다. JdbcTemplate은 스프링이 JDBC의 반복 작업(연결 열고 닫기, 예외 변환, 결과 순회)을 대신해 주는 클래스다.

  • Bean Validation

    Bean Validation은 객체 필드에 제약 어노테이션(constraint annotation)을 붙여 입력을 검증하는 자바 표준이다(Jakarta Validation, 구현체는 Hibernate Validator). 스프링은 컨트롤러 파라미터에 @Valid가 붙으면 바인딩 직후 검증을 실행한다.

보기 옵션