ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • #Spring Data JPA - 11 확장기능 - Auditing
    Spring Data JPA 2021. 3. 25. 11:00

    @EntityListeners(AuditingEntityListener.class)Auditing

    엔티티를 생성, 변경할 때 변경한 사람과 시간을 추적하고 싶으면?

    · 등록일

    · 수정일

    · 등록자

    · 수정자

     

    순수 JPA 사용

     

    우선 등록일, 수정일 적용

    package study.datajpa.entity;
    @MappedSuperclass
    @Getter
    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();
         }
    }

    · @MappedSuperclass:  jpa에서 진짜 상속이있고 속성만 내려쓰는 상속관계가 있는데

                                   MappedSuperclass는 속성을 내려서 테이블에서 같이쓸 수 있게 데이터만 공유하는 것

    · @PrePersist : JPA가 제공하는것 persist하기 전에 제공

    · @PreUpdate : 업데이트 하기 전에 발생

     

     

    - MappedSuperclass 사용X

    그냥 쓰게 되면 member에 날짜가없다

     

    - MappedSuperclass 사용O

    createddate와 updatedate가 생성된 것을 볼 수 있다. 

     

    Member class에 상속

    public class Member extends JpaBaseEntity {}

     

    확인 코드

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

    JPA 주요 이벤트 어노테이션

    · @PrePersist, @PostPersist

    · @PreUpdate, @PostUpdate

     

     

    스프링 데이터 JPA 사용

     

    설정

    @EnableJpaAuditing → 스프링 부트 설정 클래스에 적용해야함

    @EntityListeners(AuditingEntityListener.class)  엔티티에 적용(이벤트를 기반으로 얘가 동작한다는 것)

     

    사용 어노테이션

    · @CreatedDate

    · @LastModifiedDate

    · @CreatedBy

    · @LastModifiedBy

     

    스프링 데이터 Auditing 적용 - 등록일, 수정일

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

    스프링 데이터 Auditing 적용 - 등록자, 수정자

    package jpabook.jpashop.domain;
    
    @EntityListeners(AuditingEntityListener.class)
    @MappedSuperclass
    public class BaseEntity {
       @CreatedDate
       @Column(updatable = false)
       private LocalDateTime createdDate;
       
       @LastModifiedDate
       private LocalDateTime lastModifiedDate;
       
       @CreatedBy
       @Column(updatable = false)
       private String createdBy;
       
       @LastModifiedBy
       private String lastModifiedBy;
    }


    @EntityListeners(AuditingEntityListener.class)- 이벤트를 기반으로 얘가 동작한다는 것을 알리는 어노테이션

     

    @CreatedBy @LastModifiedBy -  그냥두면값이 안들어가고 AuditorAware빈을 등록해야한다.

     

    등록자, 수정자를 처리해주는 AuditorAware 스프링 빈 등록

    @Bean
    public AuditorAware<String> auditorProvider() {
       return () -> Optional.of(UUID.randomUUID().toString());
    }

    실무에서는 세션 정보나, 스프링 시큐리티 로그인 정보에서 ID를 받음

    등록되거나 수정될떄마다 autitorProvider를 호출을 해서 결과물을 꺼내가서 값들을 자동으로 채운다.

     

    참고: 실무에서 대부분의 엔티티는 등록시간, 수정시간이 필요하지만, 등록자, 수정자는 없을 수도 있다. 그래서 다음과 같이 Base 타입을 분리하고, 원하는 타입을 선택해서 상속한다.

     

     

    등록일 수정일만 있고 등록자 수정자는 안필요한 곳이 생기는 경우 

    public class BaseTimeEntity {
    
       @CreatedDate
       @Column(updatable = false)
       private LocalDateTime createdDate;
       
       @LastModifiedDate
       private LocalDateTime lastModifiedDate;
       
    }
    
    public class BaseEntity extends BaseTimeEntity {
    
       @CreatedBy
       @Column(updatable = false)
       private String createdBy;
       
       @LastModifiedBy
       private String lastModifiedBy;
       
    }

    참고: 저장시점에 등록일, 등록자는 물론이고, 수정일, 수정자도 같은 데이터가 저장된다. 데이터가 중복 저장되는 것 같지만, 이렇게 해두면 변경 컬럼만 확인해도 마지막에 업데이트한 유저를 확인 할 수 있으므로 유지보수 관점에서 편리하다. 이렇게 하지 않으면 변경 컬럼이 null 일때 등록 컬럼을 또 찾아야 한다.

     

    참고로 저장시점에 저장데이터만 입력하고 싶으면 @EnableJpaAuditing(modifyOnCreate = false) 옵션을 사용하면 된다.

    @EnableJpaAuditing(modifyOnCreate = false)  

     

    전체 적용

    @EntityListeners(AuditingEntityListener.class) 를 생략하고 스프링 데이터 JPA 가 제공하는 이벤트를 엔티티 전체에 적용하려면 orm.xml에 다음과 같이 등록하면 된다.

     

     

    META-INF/orm.xml

    <?xml version=“1.0” encoding="UTF-8”?>
    <entity-mappings xmlns=“http://xmlns.jcp.org/xml/ns/persistence/orm”
           xmlns:xsi=“http://www.w3.org/2001/XMLSchema-instance”
           xsi:schemaLocation=“http://xmlns.jcp.org/xml/ns/persistence/
          orm http://xmlns.jcp.org/xml/ns/persistence/orm_2_2.xsd”
           version=“2.2">
           
           
           <persistence-unit-metadata>
              <persistence-unit-defaults>
                 <entity-listeners>
                   	<entity-listener class="org.springframework.data.jpa.domain.support.AuditingEntityListener”/>
                 </entity-listeners>
              </persistence-unit-defaults>
           </persistence-unit-metadata>
    
    </entity-mappings>

     

    댓글

Designed by Tistory.