Framework/Hibernate

하이버네이트(hibernate) POJO에 데이터 입력(setMethod) 를 제한하기 위한 방법 RuntimeException

jeeyong 2017. 2. 28. 11:05

빌링(billing)용 데이터 베이스를 설계와 개발 중 인데, 빌링 개발은 높은 난위도를 가진 시스템인 것을 세삼 느낀다. 

최근 개발 중에 특별한 이슈가 생겼는데, 해결하는 과정에서 알게 된 내용이 있어 기록한다.


다른 버젼에서 다르게 동작할 수 있으므로 스펙을 기록한다.

DB 시스템은 mysql, 

persistence framework은 Hibernate3, Hibernate-jpa-2.0-api-1.0.1.final


본론,

매출이라는 데이터는 매우 특별해서 어느 특정 시점이 되면 절대 데이터는 바뀌지 않아야한다. (즉, 프로그램으로 따지면 final 속성이 붙어야 한다는 것이다. DB 클라이언트를 이용해 바로 update 하는 건 막을 방법이 없으므로 제외한다.)

이 규칙을 Service단에서 더 좋은건, POJO Instance내에서 제약을 줄 수 있으면 좋겠다는 생각을 했다.

Hibernate Transaction를 이용해서 service단에서 수정을 가하려고 할 경우 Exception 과 함께 자동으로 롤백(roll-back) 되기를 원한다.

POJO  setMethod내에서 특정 조건에 RuntimeException을 호출하도록 하면 된다. 반드시 unchecked Exception 을 호출해야 롤백이 가능하다 checked Exception 은 롤백 지원을 하지 않는다. (참고 http://www.nextree.co.kr/p3239/ )

그래서 Sales 객체내에 setMethod(set*) 에 Sales.isLock 값이 true일 경우, RuntimeException을 던지는 것으로 간단하게 해결했다. 

라고 생각했다.

그러나 해결하지 못한 또하나 이슈가 생겼다. 간단히 POJO를 가져오는 select 상황에서도 Exception이 발생한 것이다.

hibernate는 POJO attribute 에 데이터를 입력할때, setMethod를 이용한다. 그렇기 때문에 select 상황에서 setMethod를 호출하기 때문에 isLock 값이 true로 입력된 상황에서 다른 attribute 를 수정하려고 할 경우RuntimeException이 발생하게 된다. 

방법은 두가지다. 

첫번째는 처음 hibernate에서 DB 데이터를 끌어와서 POJO에 주입할때는 예외로 처리하는 방법,(Hibernate에서 POJO에 데이터를 주입할때 생성자(constructor)를 사용하는 방법이 있다면 가능하겠다,)

두번째는 제약조건에 중심이 되는 isLock 값을 가장 나중에 입력하게 하는 방법이다.

나는 두번째 방법으로 해결했다. 

hibernate가 POJO attribute에 주입하는 순서만 컨트롤하면 간단하게 해결되는 일이기 때문이다. 그러기 위해서 좀더 하이버네이트에 대한 이해가 필요하다.

내가 진행중인 프로젝트는 POJO 셋팅을  xml 로 하고 있어 sales.hbm.xml 에서 테스트를 진행하게 되었다. (어노테이션을 이용한 방법은 테스트 해보지 못했다.)

알아내는 방법은 쉬웠다. Log에 찍힌 Exception을 보니 다행히 isLock 아래 있던 (xml설정상으로) attribute 에서 발생한것이다. 바로 난 isLock 설정을 가장 아래로 배치했다.

테스트 결과는 성공!.

 좀더 다양한 상황에서 잘 동작하는지 필드테스트를 해봐야 하겠지만 지금으로서는 만족스런 설계가 되었다. 

아직 확실한 내용이 아니기 때문에 비공개로 해놓는다. 만약 필드테스트 이후에도 문제가 없다면 이 문서는 공개로 수정해서 공유하도록 할 생각이다.