[66해빗 페이백 챌린지] 24일차

tree·2023년 5월 26일
0

트랜잭션 문제 해결 - 트랜잭션 매니저1

  • 스프링이 제공하는 트랜잭션 매니저를 코드에 직접 적용해보자.

  • DataSourceUtils

    • 커넥션 동기화를 고려해 커넥션 객체를 반환하고 종료한다.
    • DataSourceUtils.getConnection(dataSource);
      • 트랜잭션 동기화 매니저에 동기화된 커넥션이 있으면 그것을 반환한다.
      • 만약 트랜잭션 동기화 매니저에 동기화된 커넥션이 없으면 데이터 소스로부터 커넥션을 가져와 반환한다.
    • DataSourceUtils.releaseConnection(con, dataSource);
      • 커넥션 객체 사용 후 바로 종료하게 되면 트랜잭션 중간에 커넥션 객체가 종료되는 문제가 발생한다. 커밋 or 롤백할 때까지 커넥션 객체는 살아 있어야 한다.
      • 트랜잭션을 사용하기 위해 동기화된 커넥션은 닫지 않고 그대로 둔다.
        • 나중에 커밋 또는 롤백을 하면 트랜잭션 매니저가 커넥션을 종료한다
      • 동기화된 커넥션이 아닌 경우에는 커넥션을 종료한다.
  • 사용 예제

    @Slf4j
    @RequiredArgsConstructor
    public class MemberService {
    
      private final PlatformTransactionManager txManager;
      private final MemberRepository memberRepository;
    
      public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        //트랜잭션 시작
        TransactionStatus status = txManager.getTransaction(new DefaultTransactionDefinition());
    
        try {
          //비즈니스 로직
          txManager.commit(status); //성공시 커밋
        } catch (Exception e) {
          txManager.rollback(status); //실패시 롤백
          throw new IllegalStateException(e);
        }
      }
    }
    • private final PlatformTransactionManager txManager
      • 트랜잭션 매니저 주입
      • 사용하는 DB 접근 기술에 맞는 트랜잭션 매니저 구현체가 주입된다.
    • TransactionStatus status = txManager.getTransaction(new DefaultTransactionDefinition())
      • status 반환
        • 현재 트랜잭션의 상태 정보를 반환한다.
        • 이후 커밋, 롤백할 때 사용한다.
      • new DefaultTransactionDefinition()
        • 트랜잭션과 관련된 옵션을 지정한다(차후 설명).
    • txManager.commit(status), txManager.rollback(status)
      • 커밋 또는 롤백

트랜잭션 문제 해결 - 트랜잭션 매니저2

  • (1) transactionManager.getTransaction()을 호출한다.
  • (2) 트랜잭션 매니저는 데이터 소스로부터 커넥션 객체를 가져온다.
  • (3) 세션의 커밋 모드를 수동으로 바꾸어 트랜잭션을 시작한다.
  • (4) 트랜잭션 동기화 매니저에 쓰레드에 지정된 보관함에 커넥션을 보관한다.

  • (6) 비즈니스 로직 수행 과정에서 리포지토리 메서드를 호출한다.
  • (7) DataSourceUtils.getConnection(dataSource)를 호출해 트랜잭션 동기화 매니저로부터 동기화된 커넥션을 가져온다.
    • 동기화된 커넥션이 없으면 데이터 소스로부터 가져오지만 여기서는 트랜잭션 수행 상황이므로 동기화된 커넥션이 없는 경우는 배제하겠다.
  • (8) 가져온 커넥션을 사용해 SQL문을 수행한다.
  • 커넥션 사용이 끝나면 DataSourceUtils.releaseConnection(con, dataSource)을 호출해 커넥션 객체를 트랜잭션 동기화 매니저에 반납한다.

  • (9) 커밋 또는 롤백 메소드를 호출한다.

  • (10) 트랜잭션 매니저는 트랜잭션 동기화 매니저로부터 커넥션을 가져온다.

  • (11) 커밋 또는 롤백을 수행한다.

  • (12) 리소스를 정리한다.

    • 세션의 커밋 모드를 자동 커밋 모드로 변경한다.
    • con.close()하여 커넥션 객체를 종료하거나 커넥션 풀에 반납한다.
  • 정리

    • 트랜잭션 매니저는 2가지 역할을 한다.
      • 트랜잭션 추상화
        • 트랜잭션 수행을 인터페이스로 추상화하여 서비스 계층이 특정 DB 접근 기술의 트랜잭션 수행 코드에 의존하지 않도록 한다.
      • 리소스 동기화
        • 트랜잭션 처리를 위해서는 같은 커넥션 객체를 필요로 한다.
        • 트랜잭션 매니저가 내부적으로 쓰레드 로컬을 이용해 커넥션을 동기화하는 트랜잭션 동기화 매니저를 사용함으로써 서비스 계층에서 리포지토리 계층으로 커넥션 객체를 넘겨줄 필요가 없어졌다.

0개의 댓글