본문 바로가기
스프링/JPA

Envers / spring-data-envers

by 공부 안하고 싶은 사람 2021. 8. 3.
반응형

개요

Envers 모듈은 Hibernate 및 JPA와 함께 작동하는 핵심 Hibernate 모델입니다.

Envers 모듈은 엔티티 클래스를위한 쉬운 감사 / 버전 관리 솔루션을 제공하는 것을 목표로합니다.

  • 하이버네이트 핵심 모듈
  • JPA 스펙에 정의된 모든 매핑 감사
  • 엔티티의 변경 이력을 자동 관리
  • 트랜잭션 단위의 통합 Revision 관리 (Snapshot)
    • REVINFO 테이블은 revision_id 와 Timestamp만 가지고 있고, 이력 테이블은 별도로 존재함. 한 트랜잭션 내에서 발생한 변경사항을 revision_id 1이라는 이력으로 여러 이력테이블에 각각 저장, revision_id 1인 항목의 해당 트랜잭션에서 변경된 모든 이력을 감사(audit)가능함

 

 

의존성

implementation('org.springframework.data:spring-data-envers')

예제에선 Spring-data-jpa 필요

 

 

 

설정

Envers 설정

DB connection이 하나 일 경우엔 Application에

@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)

@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class)
@SpringBootApplication
public class Application {

다중 Connection인 경우 사용할 Connection Config위치에

@Configuration
@EnableJpaRepositories(
        repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean.class, // 설정 추가
        entityManagerFactoryRef = "",
        transactionManagerRef = "",
        basePackages = {
                            //repository package 경로
        })
public class FirstDataManagerConfig {

 

 

변경감지

변경감지 하고자 하는 위치에 @Audited

(클래스(전체) / 필드(부분)으로 설정가능)

@Audited
@Entity(name = "Customer") 
public static class Customer {
    @Id 
  private Long id;
    private String firstName;
}
@Entity
public class Person {
    @Id @GeneratedValue 
    private Integer id;
  @Audited
  private String name;
}

 

 

 

 

변경시점

default로 REVINFO 테이블에 변경 시점이 기록된다.

테이블을 커스터마이징 하려면

@RevisionEntity, @RevisionNumber, @RevisionTimeStamp를 사용하여 커스터마이징 할 수 있다.

@Entity
@Table(name = "CustomRevisionInfo")
@RevisionEntity
public class CustomRevisionInfo implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @RevisionNumber
    private long rev;

    @RevisionTimestamp
    private Date createdAt;
}

혹은

org.hibernate.envers.default_schema: #(default: null)
#@AuditTable( schema="…" )

org.hibernate.envers.revision_field_name: #(default: REV)
org.hibernate.envers.revision_type_field_name: #(default: REVTYPE)

 

 

 

변경이력

감시 설정한 변경이력에 대한 데이터는 Tablename_AUD로 저장된다.

커스터마이징

org.hibernate.envers.audit_table_prefix: 
org.hibernate.envers.audit_table_suffix: #default: _AUD

REVTYPE

RevisionType Enum

  • 0: (ADD) 행 추가
  • 1: (MOD) 행 수정
  • 2: (DEL) 행 삭제

 

 

 

 

이력조회(AuditReader를 통한)

복잡한 조건의 이력조회를 QueryDsl과 유사한 방식으로 조회할 수 있다.

@PersistenceContext(unitName = "")
private EntityManager em;

...

AuditReader auditReader = AuditReaderFactory.get(em);
return auditReader.createQuery()
  .forRevisionsOfEntity(IotManagementDevice.class, true, true) // 설치일자 검색 
  .add(AuditEntity.property("instl_de").eq("2020-06-01")) // 수정 항목만 검색 
  .add(AuditEntity.revisionType().eq(RevisionType.MOD)) // 정렬 조건 
  .addOrder(AuditEntity.revisionNumber().desc()) .getResultList();
@PersistenceContext(unitName = "")
private EntityManager em;

...


AuditReader auditReader = AuditReaderFactory.get(em);
return auditReader.createQuery() 
  .forRevisionsOfEntity(IotManagementDevice.class, true, true) // 페이징 조건 
  .setFirstResult(0) 
  .setMaxResults(pageSize) 
  .getResultList();

 

 

 

RevisionRepository 인터페이스

JpaRepository처럼 RevisionRepository을 상속받으면 JpaRepository뿐만 아니라 이력조회에 대한 여러 함수를 쉽게 사용할 수 있다.

@NoRepositoryBean
public interface RevisionRepository extends Repository<T, ID> {
    //최근 리비전 조회 Revision<N, T> 
  findLastChangeRevision(ID id);
  //id를 사용하여 해당 id의 모든 리비전 조회 
  Revisions<N, T> findRevisions(ID id); 
  //리비전을 페이징 처리하여 조회 
  Page<Revision<N, T>> findRevisions(ID id, Pageable pageable); 
  //특정 리비전 조회 Revision<N, T> 
  findRevision(ID id, N revisionNumber); 
}
Revision<Long, IotManagementDevice> revision = repository.findRevision(iotManagementDevice.getId(), 1);

IotManagementDevice entity = revision.getEntity();   // 엔티티
Long revisionNumber = revision.getRevisionNumber();  // 리비전
DateTime dateTime = revision.getRevisionDate();      // 변경 날짜
Page<Revision<Long, IotManagementDevice>> result = repository.findRevisions(iotManagementDevice.getId(), new PageRequest(**0, 10**, **RevisionSort.desc()**)); 
result.**getTotalElements**(); // 전체 수
result.**getContent**(); // 내용

 

 

 

참고 : https://directori.tistory.com/138

 

 

Hibernate ORM 이력관리 모듈 Envers 사용 가이드

개요 Envers 모듈은 Hibernate 및 JPA와 함께 작동하는 핵심 Hibernate 모델입니다. 사실 독립형이든, WildFly이든 JBoss AS, Spring, Grails 등이든 Hibernate가 작동하는 모든 곳에서 Envers를 사용할 수 있습니..

directori.tistory.com

 

 

728x90
반응형

'스프링 > JPA' 카테고리의 다른 글

Querydsl  (0) 2021.08.24
Spring-Data-Jpa  (0) 2021.08.06
JPA 최적화, Hint  (0) 2021.06.04
JPA 변경/삭제 @Modifying  (0) 2021.06.04
FK가 PK가 아닌 다른 컬럼과 연관관계가 있을 때  (0) 2021.05.31

댓글