caffeine-library / pro-spring-5

🌱 전문가를 위한 스프링5를 읽는 스터디
5 stars 0 forks source link

[keyword] 8장 스프링에서 JPA2로 데이터 액세스하기 (2) #64

Closed binchoo closed 3 years ago

binchoo commented 3 years ago

주제

8장 스프링에서 JPA2로 데이터 액세스하기 (2)를 읽고 중요✨ 하다고 생각하는 키워드와 선택한 이유에 대해서 코멘트로 달아주세요.

연관챕터

63

binchoo commented 3 years ago

이해하기 쉬운 예제 추가 필요)

Hibernate Envers Auditing 전략

Envers는 엔터티 자료에 대한 버전 관리를 제공한다. 엔터티 클래스 혹은 필드에 @Audited를 명시하면, 하이버네이트는 각 엔터티에 대응하는 이력 테이블을 생성한다.

감사 대상인 엔터티에 변경이 가해질 때마다 이력이 업데이트 된다. 이력 정보를 저장하고 읽어들이는 전략에는 2가지가 있다.

default audit strategy

감사 대상 테이블에 row가 삽입/갱신/삭제될 때마다 이력 테이블에도 row가 삽입되며 해당 row가 유효했던 revision 번호도 함께 저장한다. 이력 테이블에 추가된 row들은 결코 수정될 일이 없다.

조회 코드 예

List<Book> books = reader.createQuery()
    .forEntitiesAtRevision(Book.class, 3).getResultList();
SELECT
  book_aud0_.id AS id1_3_,
  book_aud0_.rev AS rev2_3_,
  book_aud0_.revtype AS revtype3_3_,
  book_aud0_.isbn AS isbn4_3_,
  book_aud0_.title AS title5_3_,
  book_aud0_.author_id AS author_i6_3_
FROM book_audit book_aud0_
WHERE book_aud0_.rev =
  (
    SELECT MAX(book_aud1_.rev)
    FROM book_audit book_aud1_
    WHERE book_aud1_.rev <= ?
    AND book_aud0_.id = book_aud1_.id
  )
AND book_aud0_.revtype <> ?

validity audit strategy

감사 대상 테이블에 row가 삽입/갱신/삭제될 때마다 이력 테이블에도 row가 삽입되며 해당 row가 유효했던 start-revision 번호도 저장한다. 그리고 이미 존재하는 이력 rows의 end-revision 필드에 방금 전 start-revision와 똑같게 수정한다. 따라서 특정 버전을 조회하는 쿼리를 'start-revision ~ end-revison' 범위를 명시하는 형태를 사용할 수 있게 된다.

조회 코드 예

자바는 위랑 동일

SELECT
  book_aud0_.id AS id1_3_,
  book_aud0_.rev AS rev2_3_,
  book_aud0_.revtype AS revtype3_3_,
  book_aud0_.revend AS revend4_3_,
  book_aud0_.isbn AS isbn5_3_,
  book_aud0_.title AS title6_3_,
  book_aud0_.author_id AS author_i7_3_
FROM book_audit book_aud0_
WHERE book_aud0_.rev <= ?
AND book_aud0_.revtype <> ?
AND (book_aud0_.revend > ?
OR book_aud0_.revend IS NULL)

SELECT 서브 쿼리 없이 더 효율적인 쿼리가 작성된다.

참고: http://devguis.com/11-audit-spring-boot-persistence-best-practices-optimize-java-persistence-performance-in-spring-boot-applications.html

JasonYoo1995 commented 3 years ago

8.7 JpaRepository 사용하기

binchoo commented 3 years ago

Hibernate Envers Auditing 이력 테이블 예시

https://github.com/caffeine-library/pro-spring-5/issues/64#issuecomment-939415148 주제가 직관적으로 와닿지 않아 실제 이력 테이블 모습을 살펴본 것입니다.

시나리오 1

1. 김이름 추가
2. 이이름 추가
3. 박이름 추가
4. 김이름->김삼름 변경
5. 이이름->이삼름 변경
6. 박이름->박삼름 변경

위 시나리오를 수행하면 SINGER_AUDIT 테이블은 그림처럼 됩니다.

image

이제 엔버스의 감사 전략에 따른 SINGER_AUDIT_H (이력 테이블) 모습을 살펴 봅니다.

기본 감사 전략

image 이력 테이블을 보면, 시나리오에서 수행한 각 조작이 낳은 엔터티 결과물에 AUDIT_REVSION 값이 붙어서 기록된 걸 볼 수 있습니다. (붉은 부분은 기본 감사 전략에선 쓰지 않는 리던던트한 칼럼입니다.)

유효성 감사 전략

image 유효성 감사 전략에서는 AUDIT_REVISION 뿐만 아니라 AUDIT_REVISION_END 값도 기록됩니다. AUDIT_REVISION_END 값이 null이 아니라면 엔터티가 해당 리비전부터 무효가 되었음을 나타냅니다.

예를 들어 4번 조작에서 '김이름'이 '김삼름'이 되었으므로 '김이름'은 1~3 리비전동안 유효하고 4 리비전부터 무효입니다.

핵심 개념


시나리오 2

배치 수정에 대해서도 한 번 살펴보겠습니다. (유효성 감사 전략만)

1. 김이름 추가
2. 이이름 추가
3. 박이름 추가
4. 한 번에 수정
김이름->김삼름 변경
이이름->이삼름 변경
박이름->박삼름 변경

image

시나리오의 4번째 조작은 한 번에 값들을 수정하는 쿼리를 날리는 것입니다. 따라서 이력 테이블에 3개의 row가 추가되었고 리비전은 4가 동일하게 붙습니다. 기존의 이력의 AUDIT_REVISION_END에 4를 붙여, 리비전 4부터 이들이 무효임을 기록해줍니다.

시나리오 3

배치 삭제에 대해서도 한 번 살펴보겠습니다. (유효성 감사 전략만)

1. 김이름 추가
2. 이이름 추가
3. 박이름 추가
4. 모두 삭제

image 엔터티가 삭제될 것이기 때문에 이력 테이블에 NOT NULL 조건을 없애줍니다. 파란색 부분을 살펴봅시다. 엔터티 삭제가 발생하면 이력 테이블은 해당 ID 값은 유지하되 이외 값들은 null로 날려버립니다.

핵심 개념


하나의 엔터티에 대해 변화를 추적하려면 어떻게 할까요?

SELECT * FROM SINGER_AUDIT_H WHERE ID=1 ORDER BY AUDIT_REVISION;

image

binchoo commented 3 years ago

시나리오 2 변형

1. 김이름 추가
2. 이이름 추가
3. 박이름 추가
4. 배치 수정 쿼리
박이름->박삼름 변경
김이름, 이이름 변경 없이

image

[수행 후 이력 테이블] image

배치 수정 쿼리에 수정 없는 2개의 엔터티가 포함되었는데요 이러면 수정이 일어난 '박이름'->'박삼름' 엔터티만 이력이 추가됩니다~