JPA Auditing
'Audit'란 '감시하다'라는 뜻으로, 각 데이터마다 '누가', '언제' 데이터를 생성했고 변경했는지 감시한다는 의미로 사용됩니다.
엔티티 클래스에는 공통적으로 들어가는 필드가 있을 수 있습니다. 예를 들어, '생성 일자'와 '변경 일자', '생성 주체'와 '변경 주체' 같은 것 입니다.
이러한 필드들은 매번 엔티티별로 생성하거나 변경할 때 값을 주입해야 하는 번거로움이 있습니다.
이 같은 번거로움을 해소하기 위해 Spring Data JPA에서는 이러한 값을 자동으로 넣어주는 기능을 제공합니다.
JPA Auditing 기능 활성화
@EnableJpaAudting
@EnableJpaAuditing 어노테이션은 JPA Auditing을 활성화하는 역할을 합니다.
이 어노테이션은 @SpringBootApplication 어노테이션 밑에 추가할 수 있지만, 별도로 클래스를 만들어서 적용시키는 방법도 있습니다.
@SpringBootApplication
@EnableJpaAuditing
public class MyApplication {
// ... application logic
}
또는
@Configuration
@EnableJpaAuditing
public class JpaAuditingConfiguration {
}
BaseEntity 만들기
코드의 중복을 없애기 위해서 각 엔티티의 공통으로 들어가게 되는 칼럼(필드)을 하나의 클래스로 빼는 작업을 수행하는 것이 일반적입니다.
아래는 예시 BaseEntity 클래스 입니다.
@Getter
@Setter
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
}
주요 어노테이션은 다음과 같습니다.
- @MappedSuperclass: JPA의 엔티티 클래스가 상속받을 경우 자식 클래스에게 매핑 정보를 전달합니다.
- @EntityListeners: 엔티티를 데이터베이스에 적용하기 전후로 콜백을 요청할 수 있게 하는 어노테이션입니다.
- AuditingEntityListener.class 엔티티의 Auditing 정보를 주입하는 JPA 엔티티 리스너 클래스입니다.
- @CreatedDate: 데이터 생성 날짜를 자동으로 주입하는 어노테이션입니다.
- @LastModifiedDate: 데이터 수정 날짜를 자동으로 주입하는 어노테이션 입니다.
다음은 BaseEntity를 상속받은 엔티티 클래스 예시입니다.
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
@Table(name = "product")
public class Product extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long number;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private Integer price;
@Column(nullable = false)
private Integer stock;
}
이 엔티티는 위에서 구현한 BaseEntity의 createdAt과 updatedAt 을 포함하여 필드를 가지고 있습니다.
참고로 어노테이션에 callSuper = true는 부모 클래스의 필드를 포함하는 역할을 수행합니다.
생성한 주체, 수정한 주체를 포함시키려면 우선 AuditorAware 인터페이스를 구현해야 합니다.
public class CurrentAuditor implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
// Replace with your logic to retrieve the current user ID
// This is an example, adjust based on your authentication mechanism
return Optional.ofNullable(SecurityContextHolder.getContext().getAuthentication().getName());
}
}
그리고 BaseEntity에 생성 주체, 수정 주체 필드를 추가합니다.
@Getter
@Setter
@ToString
@MappedSuperclass
@EntityListeners(AuditingEntityListener.class)
public class BaseEntity {
@CreatedDate
@Column(updatable = false)
private LocalDateTime createdAt;
@LastModifiedDate
private LocalDateTime updatedAt;
@Column(name = "created_by")
@CreatedBy
private String createdBy;
@Column(name = "last_modified_by")
@LastModifiedBy
private String lastModifiedBy;
}
참고
- 스프링 부트 핵심 가이드 "스프링 부트를 활용한 애플리케이션 개발 실무" , 장정우, 2022
- Google Gemini
- https://github.com/wikibook/springboot/blob/main/chapter8_advanced_jpa/src/main/java/com/springboot/advanced_jpa/data/entity/BaseEntity.java
'Development > Spring' 카테고리의 다른 글
[Spring] 영속성 전이(Cascade)와 고아 객체(Orphan) (0) | 2024.03.05 |
---|---|
[Spring] 연관 관계 매핑하기 (1) | 2024.03.05 |
[Spring] QueryDSL (2) | 2024.03.01 |
[Spring] JPA의 정렬과 페이징 처리 (0) | 2024.02.29 |
[Spring] JPQL (JPA Query Language)과 쿼리 메서드 (1) | 2024.02.28 |