2011-12-15 5 views
2

현재 JPA를 사용하지만 JPA EnitytManager (및 트랜잭션)이 DAO 계층으로 범위가 지정된 응용 프로그램을 현재 리팩토링하고 있습니다. 저장소 계층과 서비스 계층도 있습니다. 서비스 계층을 트랜잭션으로 만들고 서비스 계층에 대한 요청 당 하나의 EntityManger을 갖고 싶습니다. 이상적으로 JPA에 대한 내 서비스 또는 저장소 계층에 대해 알 필요가 없습니다.JPA 모델 유효성 검사 및 트랜잭션 처리

현재 리포지토리와 서비스 계층은 DAO 계층에서 분리 된 엔터티와 함께 ​​작동합니다. 모델이 변경되고 엔터티가 DAO 레이어로 병합됩니다. 새로운 구조에서 엔터티는 전체 요청 동안 관리 상태를 유지하며 1 요청은 1 트랜잭션 내에 포함됩니다. 변경 사항은 트랜잭션이 끝날 때 자동으로 커밋됩니다. 이것은 JPA의 정신에서 훨씬 더 많이 보이고 가장 일반적인 경우에 잘 작동합니다.

경우에 따라 모델이 변경되고 모델이 유효성을 검사하지만 때로는 유효성이 검사됩니다. 모델이 더 이상 유효하지 않으면 변경 사항이 저장되지 않아야합니다. 이전 구조에서는 이것은 간단했습니다 :

이 예제 프로세스에서는 기본적으로 그래프이며 전체 그래프는 유효성을 검사하고 자체 참조가 필요하지 않으며 모든 노드에 도달 할 수 있어야하며 첫 번째 노드에는 몇 가지 특별한 요구 사항이 있습니다. 최종 노드가 될지 등등. 우리는 먼저 모델을 변경 한 다음 모델을 검증합니다. 오래된

저장소 계층 코드 : 내가 생각하는 새로운 구조에서

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    processDao.merge(process); 
    messages.addInfoMessage("Process was updated succesfully"); 
} 
return messages; 

나는 세 가지 옵션이 내가 가장 좋은 방법으로 간주됩니다 하나의 질문을 해요, 또는 다른 대안이 있는지.

새로운 코드 옵션 1 :

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    throw new InvalidProcessException(messages); 
} 
return messages; 

남용이 코드 정렬 일부 비즈니스 규칙의 검증을위한 RuntimeException. 나는 이것이 베스트 프랙티스로 여겨지지 않는다고 생각하지만 트랜잭션은 롤백된다. 이것은 또한 엔티티가 유효성을 검사하지 않으면 예외를 throw하는 Bean Validation과 호환됩니다.

새로운 코드 옵션 2 :

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    em.getTransactionManager.rollback(); 
} 
return messages; 

이 코드는 JPA TransactionManager에 직접 롤백을 수행하고 내 저장소 계층과 JPA 사이의 종속성을 소개합니다.

새로운 코드 옵션 3 :

changeProcessModel(); 
messages = ProcessValidator.validate(process); 
if (messages.hasNoErrors()) { 
    messages.addInfoMessage("Process was updated succesfully"); 
} else { 
    processDao.refresh(process); 
} 
return messages; 

이 코드는 꽤 좋은 것 같다,하지만이 CascadeType.REFRESH에 의존 않습니다 제대로 새로 고칠 필요가있는 공정 엔티티 관계를 설정합니다.

또한 예를 들어 processDao.clear(); 또는 processDao.rollback(); 일 수 있습니다. 그러나 processDao의 범위가 전체 entityManger으로 증가 할 수 있습니다. 아주 깨끗한 방법인지 확실하지 않습니다.

이 점에 대해 어떻게 생각하십니까?

답변

0

도메인에 대한 귀하의 지속성에 대해 아는 것이 적을수록 좋습니다.그래서 도메인 모델에 대한 서비스로 지속성을 보는 대신에 나는 다음과 같은 솔루션을 제안 모델의 일부로보고에 대한 생각과 일치 :

    도메인은 항상 일관성있는 상태에 있어야한다
  • ;
  • 그래서; 모델에 들어오는 변화 (서비스에서 나왔던 UI)는 미래의 모델이 유효한지 모른 채 모델을 변경할 수 없습니다.
  • 의미 : 현재 모델은 항상 일관됩니다.

미래 모델 = CurrentModel.PerformChanges(). 유효성 검사();

어떻게이 작업을 수행 할 수 있습니까? 아마도 작업 종류의 단위를 사용했을 것입니다. (http://martinfowler.com/eaaCatalog/unitOfWork.html) 도메인 개체가 변경되고 유효성이 검사 될 때마다 도메인 개체가 변경된 이벤트가 발생합니다. 작업 단위 관리자 (Unit of Work manager)는 해당 이벤트를 가져온 다음 해당 내용이 데이터베이스에 저장되는지 확인해야합니다. 변경 사항이 확인되지 않으면 이벤트가 발생하지 않고 모델이 "유효하지 않음"으로 표시됩니다. 요청 격리 모드에서 작업하기 때문에 이것은 문제가되지 않습니다. 공유 도메인 모델에서 작업 할 때 변경 사항은 도메인에서 롤백되어야합니다!

이것은 아마도 가장 학문적 인 접근 방법이지만 아마도 토론을 시작하는 데 도움이 될 것입니다. 이러한 상황에서 무엇을 할 것인가 ...