트랜잭션 적용

트랜잭션 없는 단순한 로직

@RequiredArgsConstructor
public class MemberServiceV1 {

    private final MemberRepositoryV1 memberRepository;

    public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        Member fromMember = memberRepository.findById(fromId);
        Member toMember = memberRepository.findById(toId);

        memberRepository.update(fromId, fromMember.getMoney() - money);
        validation(toMember);
        memberRepository.update(toId, toMember.getMoney() + money);
    }

    private void validation(Member toMember) {
        if (toMember.getMemberId().equals("ex")) {
            throw new IllegalStateException("이체중 예외 발생");
        }
    }
}

테스트 코드


트랜잭션 활용

  • 트랜잭션은 비즈니스 로직이 있는 서비스 계층에서 시작해야 한다. 비즈니스 로직이 잘못 되면 해당 비즈니스 로직으로 인해 문제가 되는 부분을 함께 롤백해야 하기 때문이다.

  • 그런데 트랜잭션을 시작하려면 커넥션이 필요하다. 서비스 계층에서 커넥션을 만들고 트랜잭션 커밋 이후에 커넥션을 종료해야 한다.

  • 애플리케이션에서 DB 트랜잭션을 사용하려면 트랜잭션을 사용하는 동안 같은 커넥션을 유지해야 한다. 그래야 같은 세션을 사용할 수 있다.

img.png
  • 같은 커넥션을 유지하는 가장 단순한 방법은 커넥션을 파라미터로 전달해서 같은 커넥션이 사용되도록 유지하는 것이다.

레포지토리

  • 커넥션 유지가 필요한 두 메서드가 추가되었다. 계좌이체 서비스 로직에서 호출하는 메서드이다.

    • findById(Connection con, String memberId)

    • update(Connection con, String memberId, int money)

  • 커넥션 유지가 필요한 두 메서드는 파라미터로 넘어온 커넥션을 사용해야 하기에 getConnection()코드가 있으면 안 된다.

  • 그리고 레포지토리에서 커넥션을 닫으면 안 된다. 커넥션을 전달 받은 레포지토리 뿐만 아니라 이후에도 커넥션을 계속 이어서 사용하기 때문에 이후 서비스 로직이 끝날 때 트랜잭션을 종료하고 닫아야 한다.

서비스 로직

테스트 코드

Last updated