스프링 DB 2편(데이터 접근 활용 기술)

Ch11. 스프링 트랜잭션 전파(활용) - 단일 트랜잭션

webmaster 2022. 7. 8. 18:05
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 도 같은 커넥션을 사용하면서 자연스럽게 트랜잭션 범위에 포함된다

문제 : 각각 트랜잭션이 필요한 상황이면 어떻게 해야 될까?

클라이언트 B,C에서 호출하는 Repository에서도 각각 트랜잭션이 걸렸으면 좋겠다.

  • 클라이언트 A는 MemberService부터 MemberRepository , LogRepository를 모두 하나의 트랜잭션으로 묶고 싶다.
  • 클라이언트 B는 MemberRepository 만 호출하고 여기에만 트랜잭션을 사용하고 싶다.
  • 클라이언트 C는 LogRepository 만 호출하고 여기에만 트랜잭션을 사용하고 싶다.
  • 클라이언트 A만 생각하면 MemberService에 트랜잭션 코드를 남기고, MemberRepository , LogRepository의 트랜잭션 코드를 제거하면 앞서 배운 것처럼 깔끔하게 하나의 트랜잭션을 적용할 수 있다.
  • 하지만 이렇게 되면 클라이언트 B, C가 호출하는 MemberRepository , LogRepository 에는 트랜잭션을 적용할 수 없다
728x90