전 페이지에서 봤던 서비스 계층 코드들은 트랜잭션을 사용하기 위해서 JDBC 기술에 의존하고 있다. 아래처럼..

/**
 * 트랜잭션 - 파라미터 연동, 풀을 고려한 종료
 */
@Slf4j
@RequiredArgsConstructor
public class MemberServiceV2 {

    private final DataSource dataSource;
    private final MemberRepositoryV2 memberRepository;

    public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        Connection con = dataSource.getConnection();
        try {
            con.setAutoCommit(false);//트랜잭션 시작
            //비즈니스 로직
            bizLogic(con, fromId, toId, money);
            con.commit(); //성공시 커밋
        } catch (Exception e) {
            con.rollback(); //실패시 롤백
            throw new IllegalStateException(e);
        } finally {
            release(con);
        }

    }

구현 기술마다 트랜잭션을 사용하는 방법이 다르다..

JDBC : con.setAutoCommit(false)

JPA : transaction.begin()

위의 코드같은 경우는 예외만 하더라도 구현기술을 바꾸면 열심히 예외 잡아놓은 부분들 싹다 고쳐야 할 것이다!

그렇다면!!! 향후 JDBC에서 JPA 같은 다른 데이터 접근 기술로 변경하면, 서비스 계층의 트랜잭션 관련 코드도 모두 함께 수정해야 한다.

이 문제를 해결하기 위해 스프링은 어떤 해결방법을 썻을까? 슬슬 예상 가지 않냐!!

그렇다… 인터페이스로 추상화를 해놓았고,, 각각 맞는 구현체도 이미 다~ 준비되어있다…!!

image.png

Like DataSource

이렇게 되면 클라이언트는 인터페이스에만 의존하고 DI를 사용한다면 OCP 원칙을 잘 지켜진 코드를 만들 수 있을 것이다! 이제 트랜잭션을 사용하는 서비스 코드를 전혀 변경하지 않고, 트랜잭션 기술을 맘껏 변경할 수 있다!

TxManager는 이해 하기 쉬우라고 만든 그림이고, 실제로 스프링은

아래 그림처럼 PlatformTransactionManager 인터페이스로 트랜잭션을 추상화한다!

image.png

package org.springframework.transaction;

public interface PlatformTransactionManager extends TransactionManager {

	TransactionStatus getTransaction(@Nullable TransactionDefinition
	definition)
			throws TransactionException;
			
	void commit(TransactionStatus status) throws TransactionException;
	void rollback(TransactionStatus status) throws TransactionException;
	}