JPA

Spring Data JPA - Auditing으로 생성일, 수정일 자동화하는 법

Cold Bean 2022. 12. 2. 00:21
728x90

JPA Auditing

생성일, 수정일은 거의 모든 엔티티에 사용되고 있다. 이런 공통적인 기능을 엔티티마다 생성해서 관리하는 것은 굉장히 비효율적이다. JPA Auditing을 사용해 하나의 엔티티로 효율적으로 사용해보자.

JPA Auditing은 데이터의 생성 또는 수정이 발생하면 자동으로 값을 넣어주는 아주아주 고마운 친구다.

@EnableJpaAuditing 추가

@EnableJpaAuditing
@SpringBootApplication
public class TodoApplication {

	public static void main(String[] args) {
		SpringApplication.run(TodoApplication.class, args);
	}

}
  • Spring Boot을 실행시키는 최상단 클래스에 추가해주자

Auditing 기능을 담당할 엔티티 생성

package toyproject.todo.audit;

import lombok.Getter;
import org.springframework.data.annotation.CreatedDate;
import org.springframework.data.annotation.LastModifiedDate;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;

import javax.persistence.Column;
import javax.persistence.EntityListeners;
import javax.persistence.MappedSuperclass;
import java.time.LocalDateTime;

@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class Auditable {
    @CreatedDate  
    @Column(updatable = false)
    private LocalDateTime createdAt;

    @LastModifiedDate
    @Column(updatable = false)
    private LocalDateTime lastModifiedAt;
}
  • @EntityListeners(AuditingEntityListner.class) : 엔티티를 DB에 저장하기 전후에 커스텀 콜백을 요청할 수 있는 어노테이션. 여기서는 AuditingEntityListner.class를 인자로 넘기게 된다.
  • @MappedSuperClass : 엔티티의 공통 매핑 정보가 필요할 때 주로 사용한다. 즉, 부모 클래스(엔티티)에 필드를 선언하고 단순히 속성만 받아서 사용하고싶을 때 사용하는 방법이다.
  • @Column(updatable = false) : 개발자에 의해서 수정되지 않도록 설정.
  • @CreatedDate : 엔티티가 생성된 날짜와 시간을 자동으로 삽입해주는 애너테이션
  • @LastModifiedDate : 엔티티가 수정될 때, 수정된 시간과 날짜를 자동으로 삽입해주는 애너테이션

Auditing을 사용할 엔티티에 상속

package toyproject.todo.todo.entity;

import lombok.*;
import toyproject.todo.audit.Auditable;

import javax.persistence.*;

@Entity
@Getter
@Builder
@AllArgsConstructor
@NoArgsConstructor(access = AccessLevel.PROTECTED)
public class Todo extends Auditable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY) // 확인 필요
    private Long todoId;

    @Column(length = 30)
    private String title;

    @Column(name = "orders")
    private Long order = 0L;

    private boolean completed = false;
}

Repository Slice Test

@DataJpaTest
class TodoRepositoryTest {

    @Autowired
    private TodoRepository todoRepository;

    @Test
    public void saveTodoTest() throws Exception {
        // given
        Todo todo = Todo.builder()
                .order(1L)
                .title("양치하기")
                .completed(false)
                .build();

        // when
        Todo saveTodo = todoRepository.save(todo);

        // then
        assertNotNull(saveTodo);
        assertNotNull(todo.getCreatedAt());
        assertNotNull(todo.getLastModifiedAt());
        assertEquals(todo.getTodoId(), saveTodo.getTodoId());
        assertEquals(todo.getTitle(), saveTodo.getTitle());
        assertEquals(todo.getOrder(), saveTodo.getOrder());
        assertEquals(todo.isCompleted(), saveTodo.isCompleted());
    }
}

테스트 성공!
Postman에서 잘 나온다.
h2 DB에서도 문제없이 나오고 있다!

참조

https://wonit.tistory.com/484

728x90