JPA Auditing
소개
데이터를 추가, 수정시 자동으로 등록 및 수정 일시를 기록해주는 기능을 지원해준다
뿐만아니라 AuditorAware 인터페이스 상속을통해 등록 및 수정 유저명까지 기록해주는 기능을 이용할 수 있다.
사전 준비
MainApplication 클래스 파일에 어노테이션 추가
다음 @EnableJpaAuditing 어노테이션을 추가해주었다
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.data.jpa.repository.config.EnableJpaAuditing;
@EnableJpaAuditing // <= 새로 추가한 어노테이션
@SpringBootApplication
public class MainApplication {
public static void main(String[] args) {
SpringApplication.run(MainApplication.class, args);
}
}
AuditorAware 인터페이스 상속받아 getCurrentAuditor() 메소드 오버라이딩 해주기
엔티티 파일에서 다음 2가지 어노테이션 @CreatedBy , @LastModifiedBy 사용시, 자동으로 저장될 값을 다음과 같은 방법으로 설정해줄 수 있다.
return 객체는 Optional<String> 타입의 로그인 아이디여야한다.
따라서, 스프링시큐리티 컨텍스트에서 가져온 값을 사용하는것이 좋다.
* 하지만, 테스트 확인을 위해 하드코딩된 문자열을 리턴해줌으로써, 작성자 및 수정자엔 테스트용이 입력되게된다.
import org.springframework.data.domain.AuditorAware;
import org.springframework.stereotype.Component;
import java.util.Optional;
@Component
public class UserAuditorAwareConfig implements AuditorAware<String> {
@Override
public Optional<String> getCurrentAuditor() {
return Optional.of("테스트용"); // 테스트용 문자열을 Optional<String> 타입으로 변환하여 리턴
/*
테스트용으로 return Optional.of("테스트용"); 코드를 사용했으나
실제로는 return SecurityUtil.getUsername(); 처럼 시큐리티 컨텍스트에서 가져온 값을 리턴해야한다
*/
}
}
사용 예시
파일 수정 : 사용중인 엔티티 클래스 파일
클래스명 위에 @EntityListeners(AuditingEntityListener.class) 어노테이션을 추가해주고
마지막으로 클래스 필드에는 다음 내용을 추가해주면 끝이다 👏
import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;
import org.springframework.data.annotation.CreatedBy;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.util.Date;
@Entity
@Getter
@Setter
@Table(name ="board")
@EntityListeners(AuditingEntityListener.class) // <= 새로 추가한 어노테이션
public class BoardEntity {
/* ...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long uid;
.. 등등
... 기존 내용은 생략 ...
... */
@CreatedDate
@Column(name="created_date")
private Date createdDate; // 작성 일시
@CreatedBy
@Column(name="created_by")
private String createdBy; // 작성자
@LastModifiedDate
@Column(name = "modified_date")
private Date modifiedDate; // 수정 일시
@LastModifiedBy
@Column(name = "modified_by")
private String modifiedBy; // 수정자
}
성능 개선 : @MappedSuperclass 어노테이션 이용하기
등록 및 수정일시, 그리고 각 유저명 필드는 게시판, 댓글 등 .. 다양한 엔티티에서 사용된다.
따라서, 해당 필드 내용을 별도의 클래스로 따로 만들고 필요한 엔티티에서 상속받아 이용하는 방식으로 개선할 수 있다.
클래스 상속으로 엔티티 필드에 추가하려면, 상속 받을 클래스에서 @MappedSuperclass 어노테이션을 이용해주면 된다.
등록일시 및 유저명만 기록하는 클래스 파일
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.util.Date;
@Getter
@MappedSuperclass // <= 엔티티에 상속받았을때, 해당 필드로 컬럼이 생성 되도록
@EntityListeners(AuditingEntityListener.class) // <= 자동 기록을 위해
public class CreatedInfo {
@CreatedDate
@Column(name="created_date")
private Date createdDate;
@CreatedBy
@Column(name="created_by")
private String createdBy;
}
그리고, 수정일시 및 유저명까지 기록하는 클래스 파일
import jakarta.persistence.Column;
import jakarta.persistence.EntityListeners;
import jakarta.persistence.MappedSuperclass;
import lombok.Getter;
import org.springframework.data.annotation.LastModifiedBy;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import java.util.Date;
@Getter
@MappedSuperclass // <= 엔티티에 상속받았을때, 해당 필드로 컬럼이 생성 되도록
@EntityListeners(AuditingEntityListener.class) // <= 자동 기록을 위해
public class ModifiedInfo extends createdInfo {
@LastModifiedDate
@Column(name = "modified_date")
private Date modifiedDate;
@LastModifiedBy
@Column(name = "modified_by")
private String modifiedBy;
}
파일 수정 : 사용중인 엔티티 클래스 파일
ModifiedInfo 클래스를 상속받으면, 수정 일시 및 유저명이 엔티티 필드에 추가된다.
그런데, 해당 클래스가 CreatedInfo 클래스를 상속받고 있기때문에 작성 일시 및 유저명도 함께 추가된다.
결과적으로 작성 및 수정 일시, 그리고 유저명이 기록되어야하는 엔티티는 ModifiedInfo 클래스를 상속받으면 된다.
만약 수정이 불가하고, 등록만 가능한 엔티티는 CreatedInfo 클래스를 상속받으면 된다.
자주 사용되는 필드를 @MappedSuperclass 어노테이션을 이용해 클래스로 빼고,
상황에 맞는 클래스를 상속받아 사용하도록 성능 개선을 할 수 있었다 👍
@Entity
@Getter
@Setter
@Table(name ="board")
// 클래스 상속으로 해당 어노테이션 필요 X -> @EntityListeners(AuditingEntityListener.class)
public class BoardEntity extends ModifiedInfo {
/* ...
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long uid;
.. 등등
... 기존 내용은 생략 ...
@CreatedDate
@Column(name="created_date")
private Date createdDate; // 작성 일시
@CreatedBy
@Column(name="created_by")
private String createdBy; // 작성자
@LastModifiedDate
@Column(name = "modified_date")
private Date modifiedDate; // 수정 일시
@LastModifiedBy
@Column(name = "modified_by")
private String modifiedBy; // 수정자
... 위 작성 및 수정일시 , 그리고 유저명도 클래스 상속으로 해결되었기때문에 주석 처리 ...
... */
}
'💻 FullStack > SpringBoot' 카테고리의 다른 글
스케줄러를 이용한 반복 작업 처리하기 (0) | 2024.03.17 |
---|---|
DBMS별 application 파일 설정 방법 (0) | 2024.03.09 |
Spring Data JPA 네이티브 쿼리 (0) | 2023.08.19 |
Spring Data JPA 쿼리 메소드 (0) | 2023.08.15 |
Spring Data JPA 로그 설정들 (0) | 2023.08.13 |