이제 트랜잭션을 써서 앞의 문제를 해결해보자!(원자성)
이를 MemberServiceV1에 적용시켜보자.!
서비스 계층의 비지니스로직인 accountTransfer 의 시작부분에서 커넥션, 트랜잭션을 시작하고 마지막 부분에서 커밋 또는 롤백을 한 뒤 커넥션을 종료하자!
트랜잭션 시작 == set autocommit false;
-> @Transactional을 붙이면 되지만 ...
Connection을 파라미터로 받는 findById
MemberRepositoryV2를 만들고 원래 findById 밑에 커넥션을 파라미터로 받는 findById를 추가하자.
-> 여기서 finally를 보면 커넥션은 닫지 않는다.
-> connection을 닫으면 안된다.
-> service계층에서 커넥션을 시작해서 넘겨주었으므로 service계층에서 커넥션을 종료해야한다.
Connection을 파라미터로 받는 update
여기서도 con=getConnection()을 지워줘야한다. -> 새로운 커넥션을 받아오니까 당연함.
여기서는 executeUpdate이므로 ResultSet이 없으므로 pstmt만 닫아주자.
MemberServiceV2
이제 con을 파라미터로 넘겨서 한 connection만을 쓰는 MemberServiceV2를 작성해보자.
각각 파라미터에 con을 넘겨준 것을 알 수 있다.
성공 시 commit, 실패 시 rollback
finally에서 커넥션을 닫아줘야 하는데,
con.close()를 하면 con이 풀에 반환이 된다.
-> 이때 해당 커넥션의 오토커밋을 켜주고 반환하자.
MemberServiceV2Test
@BeforeEach에서 모두 V2로 바꿔주자.
1. 정상이체의 경우 트랜잭션 시작과 끝 사이에 다른 커넥션을 가져오는 로그가 안찍힌다. = 같은 커넥션을 사용한다.
2. 하지만 이체 중 예외발생 테스트에서는
accountTransfer() 에서 예외가 터지고 예외 상황시 con.rollback() 해버리므로 결과적으로
A 10000원, B 10000원으로 롤백된다.
남은 문제
서비스계층에 비지니스로직보다 커넥션관련 코드가 더 많다.
커넥션을 일일히 넘겨주기도 번거롭다.
옛날엔 다 이렇게 짰다.
-> 스프링의 @Transactional 쓰자.
# 본 게시글은 인프런 김영한님의 강의를 수강 후 반복학습을 위해 정리한 내용입니다.
'Java, Spring > Spring DB 1' 카테고리의 다른 글
4-2. 트랜잭션 추상화 (0) | 2022.09.28 |
---|---|
4-1. 문제점들(서비스 계층에 트랜잭션 코드가 너무 많다.) (0) | 2022.09.27 |
3-10. 트랜잭션 - 적용1 (1) | 2022.09.25 |
3-8. DB 락 - 조회 (1) | 2022.09.23 |
3-7. DB 락 - 개념 이해, 3-8. DB 락 - 변경 (1) | 2022.09.23 |