Java에서 ORM 기술인 JPA를 사용하여 도메인을 관계형 데이터베이스 테이블에 매핑할 때 공통적으로 도메인들이 가지고 있는 필드나 컬럼들이 존재한다. 대표적으로 생성일자, 수정일자, 식별자 같은 필드 및 컬럼이 있다.
이제 위의 필드값들은 하나씩 세팅해본다고 가정했을 때,
데이터를 생성하고 수정할때, 누가, 언제했는지 알기 위한 필드들을 사용할 때 하나하나 세팅해주는 것이 아닌 JPA에서 제공해주는 어노테이션을 사용하면 더 손 쉽게 세팅할 수 있다.
JPA Auditing 이란?
Spring Data JPA에서는 Auditing이라는 기능을 제공한다. 이를 사용하여 엔티티가 생성되고, 변경되는 그 시점을 감지하여 생성시각, 수정시각, 생성한 사람, 수정한 사람을 기록할 수 있다.
1. 어노테이션 추가
JPA Auditing을 활성화
- Application 클래스나 @Configuration 어노테이션이 붙은 클래스에 @EnableJpaAuditing 어노테이션 추가
@EnableJpaAuditing
@SpringBootApplication
public class MyApplication {
...
}
Spring Data dependency 추가
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-data-jpa'
}
2. 공통 엔티티 생성
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성일시
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime modifiedAt; // 수정일시
}
abstract class 추상클래스
직접 생성해서 사용할 일이 없고, 다른 클래스의 부분 클래스라는 의미도 줄 수 있기 때문에 상속을 위해 사용해야 하는 클래스라고 abstract 키워드로 명시해주는 것이 좋다.
공통 매핑 정보가 필요할 때 사용하는 어노테이션이다.
@EntityListeners(AuditingEntityListener::class)
Auditing을 적용할 엔티티 클래스에 적용하는 어노테이션이다.
해당 어노테이션은 엔티티의 변화를 감지하여 엔티티와 매핑된 테이블의 데이터를 조작한다.
이 어노테이션은 파라미터에 이벤트 리스너를 넣어줘야하는데, 여기에 AuditingEntityListener 클래스를 넣어준다. 이 클래스는 Spring Data JPA에서 제공하는 이벤트 리스너로 엔티티의 영속, 수정 이벤트를 감지하는 역할을 한다.
AuditingEntityListener내부 코드를 보면 @PrePersist, @PreUpdate 어노테이션을 사용하는 메서드가 존재하는 것을 볼 수 있다. 이것을 통해서 Entity에 생성, 수정이 일어나면 콜백이 실행되어 시간을 만들어주는 것이다.
@CreatedDate
Entity가 생성됨을 감지하고 그 시점을 해당 필드에 기록한다.
생성일자는 수정되면 안되므로 @Column(updatable = false)을 적용해야한다.
@LastModifiedBy
Entity가 수정됨을 감지하고 그 시점을 해당 필드에 기록한다.
@CreatedBy / @LastModifiedBy
Entity가 생성되고 수정될때, 생성/수정 하는 주체가 누구인지 자동으로 기록해준다.
생성하는 주체를 지정하기 위해서 AuditorAware<T>를 지정해야 하는데, 이는 Spring Security와 관련이 있는 내용이라 추후에 설명하겠다.
3. JPA Config 설정
@CreateBy(생성자), @LastModifiedBy(수정자) 어노테이션을 사용하려면 Jpa config 에 설정을 따로 해주어야 한다.
예시 코드
- SpringSecurity를 적용하지 않고 생성/수정 주체를 임의로 삽입하는 경우
/*
spring security 적용 안되어있을 때
jpa auditing 시 해당 정보 자동입력
*/
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.of("tudy");
}
- SpringSecurity를 적용한 경우 JpaConfi의 AuditorAware<T>
@EnableJpaAuditing
@Configuration
public class JpaConfig {
@Bean
public AuditorAware<String> auditorAware() {
return () -> Optional.ofNullable(SecurityContextHolder.getContext())
.map(SecurityContext::getAuthentication)
.filter(Authentication::isAuthenticated)
.map(Authentication::getPrincipal)
.map(BoardPrincipal.class::cast)
.map(BoardPrincipal::getUsername);
}
}
Security로 Principle 객체를 구현하여 해당 username값을 넣어주면 된다.
4. 생성/수정 시각, 생성자/수정자 자동 기록하는 엔티티 예시
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
public abstract class AuditingFields {
@CreatedDate
@Column(nullable = false, updatable = false)
private LocalDateTime createdAt; // 생성일시
@CreatedBy
@Column(nullable = false, length = 100, updatable = false)
private String createdBy; // 생성자
@LastModifiedDate
@Column(nullable = false)
private LocalDateTime modifiedAt; // 수정일시
@LastModifiedBy
@Column(nullable = false, length = 100)
private String modifiedBy; // 수정자
}
참고
Spring Data JPA Auditing으로 엔티티의 생성/수정 시각 자동으로 기록
[배워보자 Spring Data JPA] JPA Auditing 기능을 사용해서 생성, 수정 일자 자동화하기
'spring 🍀 > spring-data-jpa' 카테고리의 다른 글
@MappedSuperclass 사용법 (0) | 2023.11.23 |
---|---|
JPA N+1 문제 해결과정 ( join fetch + CountQuery) (0) | 2023.11.23 |
JPA 프록시와 지연로딩/즉시로딩 (1) | 2023.11.23 |
JPA의 Entity는 기본 생성자가 왜 반드시 필요할까? (1) | 2023.11.20 |
EntityManager와 EntityManagerFactory (0) | 2023.11.20 |