[java] @Transactional 주석은 어디에 속합니까?

클래스 및 / 또는 해당 메소드 @Transactional에 배치해야합니까 DAO, 아니면 DAO 객체를 사용하여 호출하는 서비스 클래스에 주석을 추가하는 것이 더 낫습니까? 아니면 두 “레이어”에 주석을 추가하는 것이 합리적입니까?



답변

거래는 서비스 계층에 속한다고 생각합니다. 작업 단위 및 사용 사례에 대해 알고있는 사람입니다. 단일 트랜잭션에서 함께 작동해야하는 여러 DAO를 서비스에 주입 한 경우 정답입니다.


답변

일반적으로 거래는 일반적으로 서비스 수준에서 시작된다는 진술에 동의합니다 (물론 필요한 세분성에 따라 다름).

그러나 @Transactional(propagation = Propagation.MANDATORY)그 동안 발신자에서 거래를 시작하지 않은 오류를 훨씬 쉽게 감지 할 수 있기 때문에 DAO 레이어 (및 거래를 시작할 수 없지만 기존 레이어가 필요한 다른 레이어)에 추가하기 시작했습니다 ( 예를 들어 서비스). DAO에 필수 전파로 주석이 달린 경우 메소드가 호출 될 때 활성 트랜잭션이 없다는 예외가 발생합니다.

또한이 주석에 대한 모든 bean (bean post processor) @Transactional을 확인하고 서비스 계층에 속하지 않는 bean에서 Mandatory 이외의 전파 가있는 주석 이 있으면 실패하는 통합 테스트가 있습니다. 이렇게하면 잘못된 계층에서 트랜잭션을 시작하지 않습니다.


답변

트랜잭션 주석은 분리 할 수없는 모든 작업 주위에 배치해야합니다.

예를 들어 전화는 “비밀번호 변경”입니다. 그것은 두 가지 작업으로 구성됩니다

  1. 비밀번호를 변경하십시오.
  2. 변경 사항을 감사하십시오.
  3. 비밀번호가 변경된 클라이언트에게 이메일을 보냅니다.

따라서 위의 감사가 실패하면 암호 변경도 실패해야합니까? 그렇다면 트랜잭션은 약 1과 2 여야합니다 (서비스 계층에서도). 전자 메일이 실패하는 경우 (아마도 이것에 대해 안전 장치가 있어야 실패하지 않을 것입니다) 변경 암호와 감사를 롤백해야합니까?

이것들은 어디에 넣을지를 결정할 때 물어봐야 할 질문들 @Transactional입니다.


답변

전통적인 Spring 아키텍처에 대한 정답은 다른 사람들이 이미 설명한 이유로 서비스 클래스에 트랜잭션 의미 체계를 배치하는 것입니다.

Spring에서 떠오르는 트렌드는 도메인 기반 디자인 (DDD)에 대한 것입니다. Spring Roo 는 트렌드를 잘 보여줍니다. 아이디어는 도메인 객체 POJO 를 일반적인 Spring 아키텍처보다 훨씬 더 풍부하게 만들고 (일반적으로 빈혈이 없음 ), 특히 도메인 객체 자체에 트랜잭션 및 지속성 의미를 두는 것입니다. 필요한 모든 것이 간단한 CRUD 작업 인 경우 웹 컨트롤러는 도메인 개체 POJO에서 직접 작동하며 (이 컨텍스트에서 엔터티로 작동하고 있음) 서비스 계층이 없습니다. 도메인 객체간에 조정이 필요한 경우 다음과 같은 서비스 Bean 핸들을 가질 수 있습니다.@Transaction전통에 따라. 도메인 오브젝트에서 트랜잭션 전파를 설정하여 도메인 오브젝트가 REQUIRED서비스 Bean에서 시작된 트랜잭션과 같은 기존 트랜잭션을 사용하도록 할 수 있습니다.

기술적으로이 기술은 AspectJ 및를 사용 <context:spring-configured />합니다. Roo는 AspectJ 인터 타입 정의를 사용하여 엔티티 시맨틱 (트랜잭션 및 지속성)을 도메인 객체 (기본적으로 필드 및 비즈니스 메소드)와 분리합니다.


답변

일반적인 경우는 서비스 계층 수준에 주석을 달지만 실제로는 요구 사항에 따라 다릅니다.

서비스 계층에 주석을 달면 DAO 수준에서 주석을 달 때보 다 트랜잭션이 길어집니다. 예를 들어 동시 트랜잭션은 서로의 변경 사항을 볼 수 없으므로 트랜잭션 격리 수준에 따라 문제를 해결할 수 있습니다. 반복 가능한 읽기.

DAO에 주석을 달면 서비스 계층이 제공하는 기능이 단일 (롤백 가능) 트랜잭션으로 수행되지 않는다는 단점이 있으므로 트랜잭션을 최대한 짧게 유지합니다.

전파 모드가 기본값으로 설정된 경우 두 레이어에 주석을다는 것은 의미가 없습니다.


답변

레이어 @Transactional에 배치하고 예외를 @Service설정 하고 트랜잭션을 추가로 최적화합니다.rollbackForreadOnly

기본적으로 (확인되지 ​​않은 예외) @Transactional만 찾고 RuntimeException롤백을 Exception.class(확인 된 예외) 로 설정 하면 예외가 롤백됩니다.

@Transactional(readOnly = false, rollbackFor = Exception.class)

확인 된 예외와 확인되지 않은 예외를 참조하십시오 .


답변

아니면 두 “레이어”에 주석을 추가하는 것이 합리적입니까? -DAO에서 전파가 “필수”인 서비스 계층에서 DAO 방법이 항상 호출 (전파)되도록하려면 서비스 계층과 dao 계층 모두에 주석을 추가하는 것이 이치에 맞지 않습니다. 이것은 DAO 메소드가 UI 계층 (또는 컨트롤러)에서 호출되는 것을 제한합니다. 또한-특히 DAO 계층을 단위 테스트 할 때 DAO에 주석을 달면 트랜잭션 기능에 대해 테스트됩니다.