Transaction Template
왜 만들어졌나?
PlatformTransactionManager를 직접 사용하면 반복 코드가 너무 많다.
TransactionManager 직접 사용 시 문제점
public void transfer(String fromId, String toId, int money) {
TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
try {
// 비즈니스 로직 시작
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
validation(toMember);
memberRepository.update(toId, toMember.getMoney() + money);
// 비즈니스 로직 끝
transactionManager.commit(status);
} catch (Exception e) {
transactionManager.rollback(status);
throw new IllegalStateException(e);
}
}
트랜잭션 시작/커밋/롤백 코드가 매번 반복됨
try-catch-finally 블록이 계속 중복됨
실제 비즈니스 로직보다 트랜잭션 처리 코드가 더 많음
TransactionTemplate으로 해결
템플릿 메서드 패턴을 적용해서 반복 코드를 제거했다.
public void transfer(String fromId, String toId, int money) {
txTemplate.executeWithoutResult((status) -> {
// 비즈니스 로직만 집중!
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
validation(toMember);
memberRepository.update(toId, toMember.getMoney() + money);
});
}
언제 쓰는가?
@Transactional
어노테이션 대신 프로그래밍 방식으로 트랜잭션을 제어하고 싶을 때조건에 따라 트랜잭션을 다르게 처리해야 할 때
기본 사용법
@Service
public class MemberService {
private final TransactionTemplate txTemplate;
private final MemberRepository memberRepository;
public MemberService(PlatformTransactionManager txManager, MemberRepository memberRepository) {
this.txTemplate = new TransactionTemplate(txManager);
this.memberRepository = memberRepository;
}
public void transfer(String fromId, String toId, int money) {
txTemplate.executeWithoutResult((status) -> {
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
validation(toMember);
memberRepository.update(toId, toMember.getMoney() + money);
});
}
}
반환값이 있는 경우
public Member findMember(String memberId) {
return txTemplate.execute((status) -> {
return memberRepository.findById(memberId);
});
}
트랜잭션 설정 변경
public void customTransfer(String fromId, String toId, int money) {
TransactionTemplate template = new TransactionTemplate(txManager);
template.setIsolationLevel(TransactionDefinition.ISOLATION_READ_COMMITTED);
template.setTimeout(30);
template.executeWithoutResult((status) -> {
// 비즈니스 로직
});
}
선택지 정리
PlatformTransactionManager (직접 사용)
가장 기본적인 방식
반복 코드가 많음
실수하기 쉬움
TransactionTemplate (프로그래밍 방식)
TransactionManager의 반복 코드 문제를 해결
트랜잭션 적용 범위를 명확하게 제어 가능
조건부 트랜잭션 처리에 유리
@Transactional (선언적)
가장 간편함, 코드가 깔끔
AOP 기반이라 프록시 한계 존재
실무에서는?
대부분 @Transactional
을 쓰고, 복잡한 트랜잭션 제어가 필요할 때만 TransactionTemplate을 고려한다.
Last updated