Skip to content

Latest commit

 

History

History
53 lines (29 loc) · 3.04 KB

Envers 삽질.md

File metadata and controls

53 lines (29 loc) · 3.04 KB

Envers 삽질

엔티티 클래스에 @Audited만 붙여주면 데이터베이스 변경 이력 저장 등 감사(audit) 기능을 제공해주는 Hibernate Envers를 쓰고 있다.

감사 기능은 좋긴 한데 @Audited가 붙은 이후에는 해당 엔티티 테이블 스키마에 변경이 생기면 Envers가 감사용으로 사용하는 테이블인 _aud 테이블에도 반영해줘야 한다. 예전에 이거 안 해줘서 런타임 오류가 발생했었는데 알고 보면 간단하지만 모르는 상태에서 원인 찾는 건 쉽지 않다.

여튼 오늘은 아래와 같은 에러를 만났다.

Could not locate getter method for property [클래스이름#필드이름]

Imgur

원래 # 다음에는 필드 이름이 오는지라 null 나오기 쉽지 않은데 null 이라니.. 살짝 느낌이 서늘했는데 역시나 검색해봐도 안 나오는..

결국 이 시간까지 매달려서 해결..

상황

@Audited가 붙은 User 엔티티가 있고, 보안 각서 비슷한 NDA 엔티티가 있다. NDA에는 @Audited가 없다.

연관 관계는 일대일 단방향(NDA -> User)이다.

이 상태에서 User를 저장하면 그냥 User 엔티티의 저장은 잘 되는데, Commit 전에 Envers의 감사 기능 동작 중에 위와 같이 에러가 난다.

원인

아래와 같이 beanName이 null이기 때문에 발생하는 에러다.

Imgur

하지만 왜 null 인 값이 저기 들어가는지, 또 null 인 값이 안 들어가게 하려면 어찌해야 되는지 쉽게 알 방법이 없어서 이번에도 감에 의존하는 트라이얼 앤 에러 꽃삽질 시작..

이리저리 해보다가 답을 찾고 나서 알게 된 원인은.. 연관 관계였다.

  • @Audited가 붙어있는 User를 저장하는데 User는 NDA를 모르고,
  • NDA는 User를 알지만 NDA에는 @Audited가 안 붙어 있으면,
  • Envers가 User의 감사 데이터를 User_aud 테이블에 저장할 때,
  • User에는 존재하지도 않는 NDA 필드가 살짝 이상한 형태로 묻어들어가서 위와 같은 에러가 난다.

해결

그래서 명시적으로 저장되는 User를 기준으로 일대일 단방향(User -> NDA)으로 연관 관계를 수정하고, NDA에도 @Audited를 붙여주고 _aud 테이블 생성해서 해결..

이거 envers의 버그일 수도 있겠다 싶은 생각도 든다.

후기

여튼 경험 상 Envers의 오류가 나면 원인 찾는데 정말 많은 비용이 드는 것 같다.

최대의 단점은 감사 기능임에도 불구하고 Envers 쪽에서 에러가 나면 감사 기능만 안 되는 게 아니라 비즈니스 전체가 안 돈다는 점이다.

테스트 관점에서도 Envers의 감사 기능은 개발자가 작성한 서비스 메서드 코드의 return 문 이후에 동작하므로,
서비스 + Repository 구간만 통합 테스트를 하면 위와 같은 오류를 사전에 감지할 수 없다. 감지한다고 해도 원인 찾기 어렵기는 마찬가지고..