본문 바로가기
학습/DB

JPA를 이용해 자동으로 시간, 작성자 추가하기

코동이 2021. 12. 14.

개요


 DB 테이블에는 생성시간, 수정시간, 작성자, 수정자의 정보가 공통적으로 많이 사용됩니다. 이 공통 칼럼은 핵심 칼럼들은 아니지만 매번 일일이 만들어주어야 합니다. 따라서, 굉장히 번거롭고 귀찮은 일인데, JPA에서는 자동으로 INSERT, UPDATE를 수행하도록 방법을 만들어 두었습니다.

 

 자동 설정을 위한 Spring Data의 핵심은 "Audit"입니다. Spring Data는 Audit이라는 용어를 사용하여 어노테이션과 클래스들을 만들 수 있습니다. Audit의 사전 뜻은 "감시하다"입니다. 예를 들어, 경찰은 차량 검문소에서 음주여부 측정을 하고 음주가 적발되면 벌금을 부과합니다. 마찬가지로 JPA의 조회, 생성, 수정, 삭제 등을 감시하다가 저장을 했을 때, 생성시간, 수정시간을 추가합니다. 한단계 더 나아가, 생성시간, 수정시간 추가는 개발자가 상관하지 않아도 자동으로 생성됩니다.

 

 

코드로 알아보기


1. Auditing을 활용할 수 있도록 등록


@Configuration
@EnableJpaAuditing
public class JpaAuditingConfig {
}

 

 

 @EnableJpaAuditing@Configuration으로 등록하여, Audit 기능을 사용할 수 있도록 합니다. App.java에서 main함수에 적어주기도 하지만, 명시적으로 알려주기 위해서 따로 클래스를 만들어 등록합니다.

 

 

2. 생성시간, 수정시간을 변수로 가지는 BaseTimeEntity를 정의


@EntityListeners(value = AuditingEntityListener.class)
@MappedSuperclass
@Getter
@ToString
public class BaseTimeEntity {
	@CreatedDate
	@Column(updatable = false)
	private LocalDateTime createdDate;

	@LastModifiedDate
	private LocalDateTime updatedDate;
}

 

  • @EntityListener(value = AuditingEntiyListener.class)

어노테이션이 있으면 Entity의 변화를 감지해서 Audit을 확인합니다.

 

 

  • @MappedSuperclass

추상클래스에 사용할 수 있으며 엔티티가 될 수 없고 상속을 통해서 사용해야만 합니다.

 

 

  • @CreateDate

JPA 저장소가 save()할 때 자동으로 생성시간을 만듭니다. ( 수정시간도 똑같이 생성된다.)

 

  • @LastModifiedDate

JPA 저장소가 수정할 때 자동으로 생성시간을 만듭니다.

 

 

3. 스프링 시큐리티 로그인 정보에서 생성자, 수정자를 호출


@Configuration
@EnableJpaAuditing
public class JpaAuditingConfig {
	@Bean
	public AuditorAware<String> auditorProvider() {
		return new AuditorAwareImpl();
	}
}

 

1번에서 만든 JpaAuditingConfig를 수정해서 AuditorAware<String>을 반환하는 함수를 빈으로 등록합니다. 해당 메서드는 생성자, 수정자를 호출하기 위해 등록한 빈입니다. 생성자, 수정자를 기록할 때 호출됩니다.

 

public class AuditorAwareImpl implements AuditorAware<String> {
	@Override
	public Optional<String> getCurrentAuditor() {
		Authentication authentication = SecurityContextHolder.getContext().getAuthentication();

		if(authentication == null || !authentication.isAuthenticated()
				|| authentication.getPrincipal().equals("anonymousUser")) {
			return Optional.empty();
		}

		return Optional.of(((UserAccount)authentication.getPrincipal()).getUsername());
	}
}

 

AuditorAware<String>을 구현하면 getCurrentAuditor()를 재정의해야 합니다. 이 때, 스프링 시큐리티 인증객체를 확인해서 로그인 정보가 없으면 Optional.empty()를 , 있으면 email을 리턴하도록 합니다.

 

 

4. 생성자, 수정자를 가지는 BaseEntity를 생성


 대부분의 클래스는 생성시간과 수정시간을 갖습니다. 하지만 생성자와 수정자는 경우에 따라서 필요할수도 있고 없을수도 있습니다. 따라서, 한 곳에 모아서 만들기보다는 상속구조를 통해 실제 원하는 것만 사용하도록 구조를 열어두는 것이 낫습니다.

 

@EntityListeners(value = AuditingEntityListener.class)
@MappedSuperclass
@Getter
public abstract class BaseEntity extends BaseTimeEntity {
	@CreatedBy
	@Column(updatable = false)
	private String createdBy;

	@LastModifiedBy
	private String updatedBy;
}

 

  • @CreatedBy

JPA 저장소가 save()할 때 자동으로 생성자를 만듭니다. ( 수정자도 똑같이 생성된다.)

 

 

  • @LastModifiedBy

JPA 저장소가 수정할 때 자동으로 수정자를 만듭니다.

 

 

 

5. 실제 사용하려는 곳에 상속하여 사용


생성시간, 수정시간만 사용하려면 BaseTimeEntity를 상속합니다.

 

...
public class Account extends BaseTimeEntity
...

 

 

생성자, 수정자도 포함하려면 BaseEntity를 상속합니다.

 

...
public class Account extends BaseEntity
...

 

Account 클래스에서 직접 CreatedDate, UpdatedDate, CreatedBy, UpdatedBy를 설정하지 않아도 생성과 수정 시 자동으로 추가가 된다. 개발자는 귀찮고 반복적인 일을 JPA Data를 통해 간단하게 만들 수 있습니다.

 

 

Spring JPA Data가 제공하는 Audit 기능을 알아보았습니다.

 

가장 대표적으로 사용하는 아래 3개의 어노테이션의 각 역할과 쓰임새를 기억하도록 합니다.

 

@EnableJpaAuditing

@EntityListener(value= AuditingEntityLisnter.class)

@MappedSuperclass

반응형

'학습 > DB' 카테고리의 다른 글

HikariCP란?  (0) 2022.07.04
JPA를 이용해 페이징 만들기  (0) 2021.12.15
다형성 쿼리  (0) 2021.10.07
MERGE INTO(oracle)  (0) 2021.10.07
서브쿼리  (0) 2021.10.06