트랜잭션 적용 - 1

학습 페이지

지금까지 배운 트랜잭션 개념을 애플리케이션에서 코드로 실습해보자.

계좌이체 예제를 만들어볼 것임. 서비스단부터 만들어보자.

@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);
       //오류 케이스
        if(toMember.getMemberId().equals("ex")) {
            throw new IllegalStateException(("계좌이체중 문제발생"));
        }

        memberRepository.update(toId, toMember.getMoney() + money);
    }
}

계좌이체를 하는 동안 예외상황을 만들어보기 위해 중간에 if문을 넣었다.

먼저 정상적인 상황을 테스트해보자.

package hello.jdbc.service;

import hello.jdbc.domain.Member;
import hello.jdbc.repository.MemberRepositoryV1;
import org.assertj.core.api.Assertions;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.DisplayName;
import org.junit.jupiter.api.Test;
import org.springframework.jdbc.datasource.DriverManagerDataSource;

import java.sql.SQLException;

import static hello.jdbc.connection.ConnectionConst.*;
import static org.assertj.core.api.Assertions.*;
import static org.junit.jupiter.api.Assertions.*;

/**
 * 기본동작, 트랜잭션이 없이 중간에 문제가 발생한다.
 */
class MemberServiceV1Test {

    public static final String MEMBER_A = "memberA";
    public static final String MEMBER_B = "memberB";
    public static final String MEMBER_EX = "ex";

    private MemberRepositoryV1 memberRepository;
    private MemberServiceV1 memberService;

    @BeforeEach
    void before() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource(URL, USERNAME, PASSWORD);
        memberRepository = new MemberRepositoryV1(dataSource);
        memberService = new MemberServiceV1(memberRepository);
    }
    
    @AfterEach
    void after() throws SQLException {
        memberRepository.delete(MEMBER_A);
        memberRepository.delete(MEMBER_B);
        memberRepository.delete(MEMBER_EX);
    }

    @DisplayName("정상 이체")
    @Test
    public void accountTransfer () throws SQLException {
        //given
        Member memberA = new Member(MEMBER_A, 10000);
        Member memberB = new Member(MEMBER_B, 10000);
        memberRepository.save(memberA);
        memberRepository.save(memberB);

        // when
        //계좌이체 진행
        memberService.accountTransfer(memberA.getMemberId(), memberB.getMemberId(), 2000);
        // then
        Member findmemberA = memberRepository.findById(memberA.getMemberId());
        Member findmemberB = memberRepository.findById(memberB.getMemberId());

        assertThat(findmemberA.getMoney()).isEqualTo(8000);
        assertThat(findmemberB.getMoney()).isEqualTo(12000);
    }
}

문제가없으므로, A의 돈 2000원이 줄고, B의 돈은 2000이 늘어나야 한다.

image.png

테스트 성공했다.

image.png

이제 이체중에 예외가 발생하는 케이스이다.

image.png

memberB를 문제의 EX로 바꿔주자.

이제 예외가 터져야 한다. 예외터지는걸 검증해야 하므로