1. hibernate envers?
- Hibernate Envers : Hibernate를 기반으로하는 객체 레벨의 데이터 변경 추적 및 버전 관리 도구
- 이를 사용하면 엔티티의 변경 이력을 추적하고, 각 변경 내용을 버전 관리하여 데이터를 효과적으로 관리할 수 있음
- 별도의 변경 로그 또는 이력 관리 시스템을 구현할 필요 없이 자동으로 데이터 변경 이력을 관리해준다는 장점
envers 에서 제공하는 기능들
- REV / REV_TYPE
- REV : 순번 시퀀스
- REV_TYPE : 0은 생성, 1은 수정, 2는 삭제
- REV(Revision)의 경우 트랜잭션 단위로 저장도 가능(로우를 여러개 수정 했을 때 같은 revision 을 넣을 수도 있다)
- annotation
- @Audited - 히스토리 관리 필드(혹은 클래스)
- @NotAudited - 히스토리 관리 제외 필드(혹은 클래스)
- 조회
- 과거 특정 시점의 Revision
- 단건 조회
- 리스트 조회
- 검색 조건 지원
- 페이징 지원
- 필드 변경 여부 관리
- @Audited(withModifiedFlag = true)
- history 테이블에 name 이 있다면 name_mod 컬럼이 생기는 형태
2. Spring Data envers 실습
hibernate envers 에 비해 RevisionRepository 인터페이스 제공으로 조회가 더 편리함
1. 실습 환경은 order-receipt 과 동일
→ Java21(kotlin 1.9), Spring boot 3.2.3
2. build.gradle 설정 추가
- 공식문서 기준 Spring Data JPA 3.0 이후로 병합되었다고 했는데 여전히 추가가 필요함..
implementation("org.springframework.data:spring-data-envers")
3. application.yaml 설정 추가
# Database Settings
spring:
application:
name: spring-data-envers-practice
jpa:
properties:
org.hibernate.envers.audit_table_suffix: _history
org.hibernate.envers.do_not_audit_optimistic_locking_field: false
org.hibernate.envers.modified_flag_suffix: _mod
datasource:
url: jdbc:h2:mem:testdb;MODE=mysql;
username: sa
password:
driverClassName: org.h2.Driver
h2:
console:
enabled: true
path: /h2-console
hibernate:
hbm2ddl:
auto: create
- org.hibernate.envers.audit_table_suffix : 생성될 이력 감지 테이블 suffix (default : _AUD)
- org.hibernate.envers.revision_field_name : 버전 id 컬럼명 (default : REV)
- org.hibernate.envers.revision_type_field_name : 수정 타입 필드명 (default : REVTYPE)
- org.hibernate.envers.revision_on_collection_change : one-to-many, one-to-one 연관관계에서 매핑 여부(default : true)
- org.hibernate.envers.store_data_at_delete : 삭제시 데이터 null 설정 여부
- org.hibernate.envers.do_not_audit_optimistic_locking_field: false : @Version 컬럼 저장 여부(false 가 저장함)
- org.hibernate.envers.modified_flag_suffix : 생성될 컬럼 suffix (default: _MOD )
- hibernate.hbm2ddl.auto : create, create-drop, update 인 경우에만 테이블을 생성하기 때문에 설정 추가
→ 상용에서는 이미 테이블이 생성된 상태일테니 필요 없음. 테스트를 위한 값
- 참고) hibernate properties https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#envers-configuration
- 참고) IntelliJ 에서 h2 사용하기
https://github.com/raycon/til/blob/master/intellij/intellij-database-tool-with-h2.md
https://www.youtube.com/watch?v=8QBJMxyXIqc
4. Application에 @EnablaJpaRepositories 추가
→ basePackages 관련 설정 추가도 가능
@EnableJpaRepositories(repositoryFactoryBeanClass = EnversRevisionRepositoryFactoryBean::class)
@EnableJpaAuditing
@SpringBootApplication
class Application
fun main(args: Array<String>) {
runApplication<Application>(*args)
}
5. JPA entity 설정 추가
@Entity
@Audited(withModifiedFlag = true)
@AuditOverride(forClass = AuditingEntity::class)
@Table(name = "receiver")
@DynamicUpdate
class Receiver(
/**
* 수령자 아이디.
*/
@Id
val id: Long = 0L,
/**
* 수령자명.
*/
@Column(name = "name")
var name: String,
/**
* 수령자 휴대폰번호.
*/
@Column(name = "phone_number")
var phoneNumber: String
) : AuditingEntity()
6. RevisionRepository 상속받도록 repository 설정 추가
interface ReceiverRepository :
JpaRepository<Receiver, String>,
RevisionRepository<Receiver, String, Long>
6. 생성 / 수정 / 조회 테스트
- forRevisionsOfEntityWithChanges : 변경내역과 함께 변경 내역 엔티티 조회
Object
- Receiver : 조회 해 온 객체 정보
- LongRevisionEntity : Revision 정보
- RevisionType : 생성 / 수정 / 삭제 정보
- HashSet : 변경된 컬럼 리스트
3. 실제 적용시 주의사항
- 복잡한 조회는 hibernate envers 를 쓰는게 좋다(ex. 히스토리 조회 로직)
- querydsl 관련 기능과 쓰기 위해서는 코드 수정이 필요하다(히스토리 테이블 join 필요)
- 기존 테이블의 컬럼이 추가되거나 삭제되는 등 테이블이 수정된다 해서 수정사항이 같이 반영되지는 않는다
- rev 컬럼이 기본적으로 Integer 라 Long 으로 custom이 필요하다
반응형