728x90
회원 리포지토리와 로그 리포지토리를 하나의 트랜잭션으로 묶는 가장 간단한 방법은 이 둘을 호출하는 회원 서비스에만 트랜잭션을 사용하는 것이다
/**
* memberService @Transactional:ON
* memberRepository @Transactional:OFF
* logRepository @Transactional:OFF
*/
@Test
public void singleTx() {
//given
String username = "outerTxOff_success";
//when
memberService.joinV1(username);
//then : 모든 데이터가 정상 저장된다.
assertTrue(memberRepository.find(username).isPresent());
assertTrue(logRepository.find(username).isPresent());
}
- memberService - @Transactional ON
- MemberRepository - @Transactional OFF, LogRepository - @Transactional OFF

- 이렇게 하면 MemberService를 시작할 때부터 종료할 때까지의 모든 로직을 하나의 트랜잭션으로 묶을 수 있다.
- 물론 MemberService 가 MemberRepository , LogRepository 를 호출하므로 이 로직들은 같은 트랜잭션을 사용한다.
- MemberService 만 트랜잭션을 처리하기 때문에 앞서 배운 논리 트랜잭션, 물리 트랜잭션, 외부 트랜잭션, 내부 트랜잭션, rollbackOnly , 신규 트랜잭션, 트랜잭션 전파와 같은 복잡한 것을 고민할 필요가 없다. 아주 단순하고 깔끔하게 트랜잭션을 묶을 수 있다

- @Transactional 이 MemberService 에만 붙어있기 때문에 여기에만 트랜잭션 AOP가 적용된다.
- MemberRepository , LogRepository 는 트랜잭션 AOP가 적용되지 않는다.
- MemberService의 시작부터 끝까지, 관련 로직은 해당 트랜잭션이 생성한 커넥션을 사용하게 된다.
- MemberService 가 호출하는 MemberRepository , LogRepository 도 같은 커넥션을 사용하면서 자연스럽게 트랜잭션 범위에 포함된다
문제 : 각각 트랜잭션이 필요한 상황이면 어떻게 해야 될까?

- 클라이언트 A는 MemberService부터 MemberRepository , LogRepository를 모두 하나의 트랜잭션으로 묶고 싶다.
- 클라이언트 B는 MemberRepository 만 호출하고 여기에만 트랜잭션을 사용하고 싶다.
- 클라이언트 C는 LogRepository 만 호출하고 여기에만 트랜잭션을 사용하고 싶다.
- 클라이언트 A만 생각하면 MemberService에 트랜잭션 코드를 남기고, MemberRepository , LogRepository의 트랜잭션 코드를 제거하면 앞서 배운 것처럼 깔끔하게 하나의 트랜잭션을 적용할 수 있다.
- 하지만 이렇게 되면 클라이언트 B, C가 호출하는 MemberRepository , LogRepository 에는 트랜잭션을 적용할 수 없다
728x90
'스프링 DB 2편(데이터 접근 활용 기술)' 카테고리의 다른 글
| Ch11. 스프링 트랜잭션 전파(활용) - 전파 롤백 (0) | 2022.07.08 |
|---|---|
| Ch11. 스프링 트랜잭션 전파(활용) - 전파 커밋 (0) | 2022.07.08 |
| Ch11. 스프링 트랜잭션 전파(활용) - 서비스 계층에 트랜잭션이 없을 때 (커밋, 롤백) (0) | 2022.07.08 |
| Ch11. 스프링 트랜잭션 전파(활용) - 예제 프로젝트 시작 (0) | 2022.07.08 |
| Ch10. 스프링 트랜잭션 전파(기본) - 다양한 전파 옵션 (0) | 2022.07.08 |