TransactionTemplate

나무·2023년 11월 22일
1

스프링 DB1

목록 보기
2/3
post-thumbnail

1. 여전히 해결못한 중복코드

코드의 중복은 언제나 문제를 발생시킨다.

트랜잭션이 있을 때마다 커밋롤백이 곁다리로 추가가 되며 짜증나는 try-catch 문이 가독성 마져 왕창 떨어뜨린다.

역시 이런경우를 대비해 만능의 스프링은 또 좋은걸 제공해준다.

바로 TransactionTemplate

2. TransactionTemplate

TransactionTemplate 클래스는 TransactionOperations 라는 인터페이스를 상속받고 구현하고있다.

TransactionOperations 인터페이스

package org.springframework.transaction.support;

import java.util.function.Consumer;

import org.springframework.lang.Nullable;
import org.springframework.transaction.TransactionException;
import org.springframework.transaction.TransactionStatus;

public interface TransactionOperations {
	
	@Nullable
	<T> T execute(TransactionCallback<T> action) throws TransactionException;

	default void executeWithoutResult(Consumer<TransactionStatus> action) throws TransactionException {
		execute(status -> {
			action.accept(status);
			return null;
		});
	}

	static TransactionOperations withoutTransaction() {
		return WithoutTransactionOperations.INSTANCE;
	}
}

TransactionTemplate 의 경우 코드가 너무 길어서 그냥 대충 구조를 파악 할 수 있게 TransactionTemplate 의 부모 인터페이스 코드를 가져왔다.

자세한건 좀 더 심화과정에서 알아보고 우선 사용법만 간단히 익혀보자.(사실 이걸 사용안한다,,ㅋㅋ,,)

Service 코드

package hello.jdbc.service;

import hello.jdbc.domain.Member;
import hello.jdbc.repository.MemberRepositoryV3;
import lombok.extern.slf4j.Slf4j;
import org.springframework.transaction.PlatformTransactionManager;
import org.springframework.transaction.support.TransactionTemplate;

import java.sql.SQLException;

import java.sql.SQLException;

/**
 * 트랜잭션 - 트랜잭션 템플릿
 */
@Slf4j
public class MemberServiceV3_2 {

    private final TransactionTemplate txTemplate;
    private final MemberRepositoryV3 memberRepository;

    public MemberServiceV3_2(PlatformTransactionManager transactionManager, MemberRepositoryV3 memberRepository) {
        this.txTemplate = new TransactionTemplate(transactionManager);
        this.memberRepository = memberRepository;
    }

    public void accountTransfer(String fromId, String toId, int money) throws SQLException {
        txTemplate.executeWithoutResult((status) -> {
            //비즈니스 로직
            try {
                bizLogic(fromId, toId, money);
            } catch (SQLException e) {
                throw new IllegalStateException(e);
            }
        });
    }

    private void bizLogic(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);
    }

    ...
}

트랜잭션탬플릿 을 이용함으로써 트랜잭션 마다 반복해야했던 커밋롤백 코드들이 사라졌다.

3. 문제점

예외 처리

커밋과 롤백을 줄여서 매우 기분이 좋아졌지만 아직 짜증나는 try-catch 문이 계속 남아있다. 이는 사실 SQLException 을 처리하지 못했기 때문인데 아쉽게도 아직 이번장은 예외처리를 다루지 않기 때문에 눈물을 머금고 넘어가도록 하자.

트랜잭션 기술 로직 존재

많이 줄였음에도 불구하고 아직 트랜잭션 기술 로직에 대한 코드가 서비스단에 남아있다.

txTemplate.executeWithoutResult((status) -> {

하지만 스프링은 당연히 이 모든문제들에 대해 또 대비가 되어있었다,,, 놀라운 기술은 다음 장에서,,,

본 포스트는
김영한의 스프링 DB 1편 - 데이터 접근 핵심 원리 를 보고 정리했습니다.

profile
나는 break가 고장난 while(true) ~

0개의 댓글