14. Auditing

민정·2022년 12월 13일
0

Spring Data JPA

목록 보기
14/17
post-thumbnail

✨ 기본적으로 테이블 만들 때, 기본적으로 넣는 컬럼들

  • 등록일
  • 수정일
  • 등록자
  • 수정자

📌 등록일, 수정일은 무조건 모든 테이블에!!

이 4개의 기본적인 값을 적용하는 방법을 순수 JPA를 사용해서, 그리고 Spring Data JPA를 사용해서 적용을 어떻게 하는지 알아보자!


순수 JPA 사용

JpaBaseEntity 생성

등록일, 수정일 필드를 가지고 있는 JpaBaseEntity

@Getter
@MappedSuperclass // 진짜 상속관계는 아니고, 속성만 내려서 테이블에 넣어서 사용할 수 있게하는 것.
public class JpaBaseEntity {
    
    @Column(updatable = false) // 등록일은 실수로라도 수정할 수 없도록
    private LocalDateTime createdDate;
    private LocalDateTime updatedDate;

    @PrePersist // persist하기 전에 이벤트가 발생
    public void prePersist(){
        LocalDateTime now = LocalDateTime.now();
        createdDate = now;
        updatedDate = now;
    }

    @PreUpdate
    public void preUpdate(){
        updatedDate = LocalDateTime.now();
    }
}

JPA 주요 이벤트 어노테이션

@PrePersist : Persist하기 전에 이벤트 발생

@PostPersist : Persist한 후에 이벤트 발생

@PreUpdate : Update하기 전에 이벤트 발생

@PreUpdate : Update한 후에 이벤트 발생


@MappedSuperclass

  • 진짜 상속 관계는 아니고, 속성(필드)들만 내려서 상속받겠다.
  • @MappedSuperclass 클래스는 엔티티가 아니다.
  • 테이블과 관계가 없고, 단순히 엔티티가 공통으로 사용하는 매핑 정보를 모으는 역할
  • 직접 생성해서 사용할 일은 없으므로 추상클래스로 만드는 것을 권장

Entity에 JpaBaseEntity 상속

public class Member extends JpaBaseEntity {
	...
}

✔ Test

    @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.getCreatedDate = " + findMember.getCreatedDate());
        System.out.println("findMember.getUpdatedDate = " + findMember.getUpdatedDate());
    }

결과

  • 생성일, 수정일 컬럼 추가됨
    created_date
    updated_date

@PrePersist, @PreUpdate 잘 작동!


Spring Data JPA 사용

@EnableJpaAuditing 추가

🚨 이 설정을 잊지 않도록 주의!!

@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {

    public static void main(String[] args) {
            SpringApplication.run(DataJpaApplication.class, args);
    }
}
  • @EnableJpaAuditing : JPA의 Auditing 활성화

보통 등록일, 수정일은 기본적으로 모든 테이블에 컬럼으로 들어가고, 등록자, 수정자필요한 경우 사용한다.

BaseTimeEntity - 등록일, 수정일
BaseEntity extends BaseTimeEntity - 등록일, 수정일, 등록자, 수정자

위와 같이 만들어 필요한 것을 가져다 쓴다.

BaseTimeEntity - 등록일, 수정일

@EntityListeners(AuditingEntityListener.class)// 이벤트를 기반으로 동작함
@MappedSuperclass
@Getter
public class BaseTimeEntity {
    // 등록일, 수정일
    @CreatedDate
    @Column(updatable = false)
    private LocalDateTime createdDate;

    @LastModifiedDate
    private LocalDateTime lastModifiedDate;
}
  • column : 등록일, 수정일
  • @EntityListeners
    • Entity를 DB에 적용하기 전,후에 콜백 리스너를 요청할 수 있음
  • @CreatedDate : Entity 생성되어 저장될 때의 시간 자동 저장
  • @LastModifiedDate : 조회한 Entity의 값을 변경할 때 시간을 자동 저장

BaseEntity - 등록자, 수정자까지 포함

@EntityListeners(AuditingEntityListener.class)// 이벤트를 기반으로 동작함
@MappedSuperclass
@Getter
public class BaseEntity extends BaseTimeEntity{

    // 등록자, 수정자 - DataJpaApplication에서 설정 필요(AuditorAware)
    @CreatedBy
    @Column(updatable = false)
    private String createdBy;

    @LastModifiedBy
    private String lastModifiedBy;
}
  • column : 등록자, 수정자
    => 등록일, 수정일과는 다르게 AuditorAware 설정 필요

등록자, 수정자 처리 - AuditorAware 설정 추가

@EnableJpaAuditing
@SpringBootApplication
public class DataJpaApplication {

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

	// 등록자, 수정자 설정 필요
	@Bean
	public AuditorAware<String> auditorProvider(){
		return new AuditorAware<String>() {
			@Override
			public Optional<String> getCurrentAuditor() {
				return Optional.of(UUID.randomUUID().toString()); // 지금은 랜덤으로
			}
		};
	}
}

등록, 수정될 때마다 AudiotorProvider 호출해서 결과물을 꺼내감.

참고!

실무에서는 세션 정보나, spring security 로그인 정보에서 ID를 받음.

✔ Test

    @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.getCreatedDate = " + findMember.getCreatedDate());
        System.out.println("findMember.getUpdatedDate = " + findMember.getLastModifiedDate());
        System.out.println("findMember.getCreatedBy = " + findMember.getCreatedBy());
        System.out.println("findMember.getLastModifiedBy = " + findMember.getLastModifiedBy());
    }

결과



출처

김영한 강사님 - 인프런 실전! 스프링 데이터 JPA

https://ict-nroo.tistory.com/129

https://webcoding-start.tistory.com/53

0개의 댓글