ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Auditing - 엔티티의 생성 변경 기록
    JPA/스프링 데이터 JPA 2023. 8. 12. 14:57

    엔티티를 생성과 변경을 할 때 변경을 한 사람, 시간 기록을 남겨두면 운영 과정에서 훨씬 도움이 될 것이다.

     

     

    순수 JPA에서의 Auditing

     

    1. JpaBaseEntity라는 날짜 속성을 알려주는 엔티티를 만든다.

    @Getter
    @MappedSuperclass // 진짜 상속은 아니고 선언된 속성들만 사용한다는 것
    public class JpaBaseEntity {
    
        @Column(updatable = false)
        private LocalDateTime createdDate;
        private LocalDateTime updatedDate;
    
        @PrePersist
        public void prePersist() {
            LocalDateTime now = LocalDateTime.now();
            createdDate = now;
            updatedDate = now;
        }
    
        @PreUpdate
        public void preUpdate() {
            updatedDate = LocalDateTime.now();
        }
    }

     

     

    2. Member 엔티티에서 JpaBaseEntity를 상속 받는다.

    public class Member extends JpaBaseEntity {
        ....
    }

     

     

    3. 테스트에서 실행해보면 만든 날짜와 수정 날짜가 나온다.

    @Test
    public void JpaEventBaseEntity() throws Exception {
        //given
        Member member = new Member("member1");
        memberRepository.save(member); // @PerPersist 발생
    
        Thread.sleep(100);
        member.setUsername("member2");
    
        em.flush(); // @PreUpdate
        em.clear();
    
        //when
        Member findMember = memberRepository.findById(member.getId()).get();
    
        //then
        System.out.println("findMember.getCreatedDate = " + findMember.getCreatedDate());
        System.out.println("findMember.getUpdatedDate = " + findMember.getUpdatedDate());
    }

     

    콘솔 결과 창

    findMember.getCreatedDate = 2023-08-12T14:36:13.643212
    findMember.getUpdatedDate = 2023-08-12T14:36:13.795051

     

     

    장점은 모든 엔티티에 JpaBaseEntity를 상속 시킬 수 있다. Team의 수정시간을 보고 싶을 때에도 팀에 JpaBaseEntity를 상속 시키면 되니까 엔티티별로 따로 만들 필요가 없다.

     

     

     

     

     

    스프링 데이터 JPA 사용

     

     

    1. Main 클래스에 무조건 @EnableJpaAuditing 어노테이션 넣어줘야 함

    @EnableJpaAuditing // 필수!
    @SpringBootApplication
    public class DataJpaApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(DataJpaApplication.class, args);
    	}
    
    }

     

     

    2. BaseEntity 클래스 생성

    @EntityListeners(AuditingEntityListener.class)
    @MappedSuperclass
    @Getter
    public class BaseEntity {
    
        @CreatedDate
        @Column(updatable = false)
        private LocalDateTime createdDate;
    
        @LastModifiedDate
        private LocalDateTime lastModifiedDate;
    }

    생성 날짜는 @CreatedDate, 수정 날싸는 @LastModifiedDate로 한다.

    @EntityListeners(AuditingEntityListener.class)는 변경이 있을 때만 동작한다는 어노테이션? 그런 의미이다.

     

     

    3. Member의 상속 엔티티 교체

    public class Member extends BaseEntity {
        ....
    }

    이후의 작업은 나머지와 동일한데 스프링 데이터 JPA를 사용하니 훨씬 간편해졌다.

     

     

     

     

    - 날짜 뿐만 아니라 변경한 사용자도 알려주기

     

     

    1. BaseEntity에 엔티티 추가

    @EntityListeners(AuditingEntityListener.class)
    @MappedSuperclass
    @Getter
    public class BaseEntity {
    
        @CreatedDate
        @Column(updatable = false)
        private LocalDateTime createdDate;
    
        @LastModifiedDate
        private LocalDateTime lastModifiedDate;
    
        @CreatedBy
        @Column(updatable = false)
        private String createBy;
    
        @LastModifiedBy
        private String lastModifiedBy;
    }

    @CreatedBy는 생성한 사람, @LastModifiedBy는 수정한 사람을 칭한다.

     

     

    2. 메인 클래스에 스프링 빈 주입

    @EnableJpaAuditing
    @SpringBootApplication
    public class DataJpaApplication {
    
    	public static void main(String[] args) {
    		SpringApplication.run(DataJpaApplication.class, args);
    	}
    
    	@Bean
    	public AuditorAware<String> auditorProvider() {
    		return () -> Optional.of(UUID.randomUUID().toString());
    		// 원래는 스프링 시큐리티에서 세션을 꺼낸 다음에 그 id를 넣어줘야 한다.
    	}
    }

    auditorProvier()라는 스프링 빈을 주입한다. 원래는 UUID 값이 아니라 스프링 시큐리티나 http에서 세션을 꺼낸 다음 그 사람의 id를 넣어줘야 하는데, 지금은 예제니까 UUID를 사용했다.

     

     

    3. 테스트

    @Test
    public void JpaEventBaseEntity() throws Exception {
        //given
        Member member = new Member("member1");
        memberRepository.save(member); // @PerPersist 발생
    
        Thread.sleep(100);
        member.setUsername("member2");
    
        em.flush(); // @PreUpdate
        em.clear();
    
        //when
        Member findMember = memberRepository.findById(member.getId()).get();
    
        //then
        System.out.println("findMember.getCreatedDate = " + findMember.getCreatedDate());
        System.out.println("findMember.getUpdatedDate = " + findMember.getLastModifiedDate());
        System.out.println("findMember.getCreatedBy = " + findMember.getCreateBy());
        System.out.println("findMember.getUpdatedBy = " + findMember.getLastModifiedBy());
    }

    테스트를 해보면 시간 이외에 생성, 변경한 사람의 UUID도 출력해준다.

     

    콘솔 결과 창

    findMember.getCreatedDate = 2023-08-12T14:49:40.986619
    findMember.getUpdatedDate = 2023-08-12T14:49:41.130150
    findMember.getCreatedDate = d63da64a-e66c-48da-b173-4a940a7a4672
    findMember.getUpdatedDate = 9dd20bcb-dd73-42e2-ae4c-5f5615c961e8

Designed by Tistory.