Spring Data JPA - Auditing

2022. 7. 31. 22:10·공부/JPA
반응형

출처 : 인프런 실전! 스프링 데이터 JPA

Spring Data JPA 게시글은 대부분 인프런의 김영한님의 강의인 '실전! 스프링 데이터 JPA' 기반으로 내용을 정리했습니다.

 

Auditing

  • 엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶을 때 사용한다.
  • 기본적으로 테이블을 생성할 때 등록일과 수정일 컬럼을 넣는다. 왜냐하면 운영할 때 기본적으로 추적이 쉽기 때문이다.
    • 추가적으로 등록자, 수정자도 추가로 넣을 수 있다.
  • 위의 등록일, 수정일은 거의 모든 테이블에 공통적으로 들어가 있는 컬럼으로 생각하면 된다.(등록자, 수정자는 필요 없는 테이블에선 추가하지 않는다.)

 

순수 JPA 사용

  • JapBaseEntity.class
@Getter
@MappedSuperclass
public class JpaBaseEntity {

    @Column(updatable = false)
    private LocalDateTime createDate;
    private LocalDateTime updateDate;


    @PrePersist
    public void prePersist() {
        LocalDateTime now = LocalDateTime.now();
        createDate = now;
        updateDate = now; //수정일이 null이어도 되지만 값을 넣어두면 나중에 쿼리 날릴 때 편하다.
    }

    @PreUpdate
    public void perUpdate() {
        updateDate = LocalDateTime.now();
    }
}
  • @MappedSuperclass : 매핑 정보만 제공하도록 설정하는 애노테이션. 잘 모르면 아래 글을 참조하면 된다.
 

JPA 고급 매핑 - Mapped Superclass 매핑 정보 상속

JPA 게시글은 대부분 인프런의 김영한님의 강의인 '자바 ORM 표준 JPA 프로그래밍' 기반으로 내용을 정리했습니다. Mapped Superclass 매핑 정보 상속 테이블과 매핑하지 않고 부모 클래스를 상속받는

devhan.tistory.com

  • @Column(updatable = false) : 해당 필드를 실수로 수정하더라도 update 쿼리가 반영되지 않도록 하는 애노테이션
  • @PrePersist : em.persist()의 기능을 수행하기 전에 이벤트 성으로 동작할 수 있도록하는 애노테이션
  • @PreUpdate : update 전에 이벤트 성으로 동작할 수 있도록 하는 애노테이션

 

  • Test 코드
@Test
public void JpaEventBaseEntity() throws Exception {
    Member member = new Member("member1");
    memberRepository.save(member); // PrePersist 발생

    Thread.sleep(100);
    member.setUsername("member2");
    
    em.flush(); // PreUpdate 발생
    em.clear();

    Member findMember = memberRepository.findById(member.getId()).get();

    System.out.println("findMember.createDate() = " + findMember.getCreateDate());
    System.out.println("findMember.updateDate() = " + findMember.getUpdateDate());
}
    select
        member0_.member_id as member_i1_0_0_,
        member0_.create_date as create_d2_0_0_,
        member0_.update_date as update_d3_0_0_,
        member0_.age as age4_0_0_,
        member0_.team_id as team_id6_0_0_,
        member0_.username as username5_0_0_ 
    from
        member member0_ 
    where
        member0_.member_id=?
findMember.createDate() = 2022-07-31T21:44:17.081741
findMember.updateDate() = 2022-07-31T21:44:17.215482

 

 

스프링 데이터 JPA 사용

설정(필수)

  • @EnableJpaAuditing : 스프링 부트 설정 클래스에 적용
  • @EntityListeners(AuditingEntityListener.class) : 엔티티에 적용

 

  • DataJpaApplication.class
@EnableJpaAuditing // 추가
@SpringBootApplication
public class DataJpaApplication {
  • BaseEntity.class
@EntityListeners(AuditingEntityListener.class)
@MappedSuperclass
@Getter
public class BaseEntity {

    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createDate;
    
    @LastModifiedDate
    private LocalDateTime lastModifiedDate;
}
  • Member.class
public class Member extends BaseEntity

 

등록자, 수정자 추가

  • BaseEntity.class
@CreatedBy
@Column(updatable = false)
private String createBy;

@LastModifiedBy
private String lastModifiedBy;
  • DataJpaApplication.class
@Bean
public AuditorAware<String> auditorProvider() {
   return () -> Optional.of(UUID.randomUUID().toString());
}

이렇게 빈을 만들어두면 등록, 수정이 될 때마다 auditorProvider()를 호출해서 UUID 값을 가져온다. 테스트 코드에서 createBy와 lastModifiedBy를 출력하는 코드를 작성하여 실행시키면 다음과 같이 잘 출력 되는 걸 볼 수 있다.

findMember.createDate() = 2022-07-31T22:03:41.844716
findMember.lastModifiedDate() = 2022-07-31T22:03:41.973969
findMember.createBy() = c6fa278e-3da8-4611-9a15-36b94fe546c8
findMember.lastModifiedBy() = a4a88166-0c2f-49d5-ba20-8f1e9d049ed8

실무에서는 랜덤 값이 아닌 세션 아이디 값 등을 가져와서 세팅하면 된다.

 

! 위에서도 말했지만 등록일, 수정일은 웬만해서 모든 테이블에 들어가는 컬럼이고, 등록자와 수정자는 테이블의 성격에 따라서 들어갈 수도, 안 들어갈 수도 있다. 그런데 위의 예제와 같이 한 클래스에 등록일, 수정일, 등록자, 수정자를 모두 밀어 넣어버리면 굳이 안 들어가도 될 등록자, 수정자를 모든 테이블이 갖게 된다. 그러니 BaseTimeEntity를 따로 만들어 등록일, 수정일 필드를 세팅하고 BaseEntity에서 BaseTimeEntity를 상속받도록 세팅한다. 
반응형
저작자표시 비영리 변경금지 (새창열림)
'공부/JPA' 카테고리의 다른 글
  • Spring Data JPA - Web 확장-페이징과 정렬
  • Spring Data JPA - Web 확장-도메인 클래스 컨버터
  • Spring Data JPA - 사용자 정의 리포지토리 구현
  • Spring Data JPA - JPA Hint & Lock
데부한
데부한
어차피 할 거면 긍정적으로 하고 싶은 개발자
    반응형
  • 데부한
    동동이개발바닥
    데부한
  • 전체
    오늘
    어제
    • 분류 전체보기 (307)
      • 방통대 컴퓨터과학과 (27)
        • 잡담 (9)
        • 3학년1학기 (17)
      • 프로젝트 및 컨퍼런스 회고 (1)
        • 프로젝트 (4)
        • 한이음 프로젝트 (0)
        • 회고 (3)
      • 공부 (165)
        • Spring (37)
        • JPA (71)
        • 인프런 워밍업 클럽_BE (10)
        • Java (6)
        • React.js (27)
        • 넥사크로 (11)
        • 기타 (3)
      • 알고리즘 (85)
        • 알고리즘 유형 (10)
        • 알고리즘 풀이 (57)
        • SQL 풀이 (18)
      • 에러 해결 (13)
      • 잡담 (7)
        • 국비교육 (2)
        • 구매후기 (5)
        • 진짜 잡담 (0)
  • 블로그 메뉴

    • Github
    • Linkedin
    • 홈
    • 방명록
    • 글쓰기
    • 관리
  • 링크

  • 공지사항

  • 인기 글

  • 태그

    Java
    RESTful
    springboot
    전자정부프레임워크
    운영체제
    인프런
    JPA
    개발자
    oracle
    프로그래머스
    토비의스프링부트
    SQL
    기출문제
    자바스크립트
    백준
    에러해결
    스프링부트
    QueryDSL
    react
    방통대
    SpringBoot를 이용한 RESTful Web Service 개발
    egov
    IT
    프론트엔드
    MSA
    토이프로젝트
    Spring
    코딩테스트
    알고리즘
    넥사크로
  • 최근 댓글

  • 최근 글

  • hELLO· Designed By정상우.v4.10.3
데부한
Spring Data JPA - Auditing
상단으로

티스토리툴바