개요
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
'스프링 > 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 |
댓글