DB(스프링 tx 매니저, tx 템플릿, tx AOP, 설정법)

jhwan·2024년 12월 6일

트랜잭션 추상화

  1. 트랜잭션 추상화의 이유

    위 사진과 같이 데이터 접근 기술이 바뀔 경우(예를 들어 JPA), 비즈니스 로직과 DB 접근 처리 로직이 JPA에 맞게 변경해야 한다. 이는 단일 책임 원칙에 위배된다.

    따라서 스프링은 PlatformTransactionManager라는 인터페이스를 두어서 구현부와 분리를 하였다. 이로 인해. 비즈니스 로직은 더 이상 위와 같이 의존하지 않는다.

TransactionManager 사용법

@Slf4j
@RequiredArgsConstructor
public class MemberServiceV3_1 {

	// **데이터 접근 기술의 주입이 일어나는 곳 **
    private final PlatformTransactionManager transactionManager;
    private final MemberRepositoryV3 memberRepository;

    public void accountTransfer(String fromId, String toId, int money) throws
            SQLException {
        TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
        try {
            //비즈니스 로직
            bizLogic(fromId, toId, money);
            transactionManager.commit(status); //성공시 커밋
        } catch (Exception e) {
            transactionManager.rollback(status); //실패시 롤백
            throw new IllegalStateException(e);
        }
    }
}

transactionTemplate을 사용

사용 이유 : 매번 commit과 rollback을 적어줘야 하기 때문에, 이러한 중복코드들을 줄여주기 위해 template을 사용한다고 합니다.!

@Slf4j
public class MemberServiceV3_2 {

//    private final PlatformTransactionManager transactionManager;
    private final TransactionTemplate txTemplate;
    private final MemberRepositoryV3 memberRepository;

    public MemberServiceV3_2(PlatformTransactionManager transactionManager,
                             MemberRepositoryV3 memberRepository) {
		// Template을 사용하려면 TransactionManager를 주입받아야 함
        this.txTemplate = new TransactionTemplate(transactionManager);
        this.memberRepository = memberRepository;
    }

    public void accountTransfer(String fromId, String toId, int money) throws
            SQLException {
        txTemplate.executeWithoutResult((transactionStatus -> {
            try{
                bizLogic(fromId,toId,money);
            } catch (SQLException e) {
                throw new IllegalStateException(e);
            }
        }));
    }

한계 : 서비스 class에 비즈니스 로직만 있는 것이 아니라, 트랜잭션 로직도 같이 있다는 한계가 있다. 이는 서비스 유지보수하기가 어렵게 만든다. 해결 방법은 AOP이다.! @Transactional

AOP @Transactional

method 위에다 @Transactional을 붙여주면 스프링이 해당 메소드를 상속받은 프록시 객체를 만든다. 실행 시에, 트랜잭션이 실행된다.

데이터소스 자동등록

  • application.properties에 있는 속성을 사용해서 DataSource를 생성한다.
  • 스프링 부트가 기본으로 생성하는 dataSource는 HikariDataSource이다. 이 설정 또한 application.properties를 통해 지정할 수 있다.
  • 트랜잭션 매니저를 자동으로 스프링 빈에 등록한다. 자동으로 등록되는 스프링 빈 이름은 tranactionManager이다.

database part를 정리하자면

Connection - db와 연결
DataSource(Hikari) - Connection들을 가지고 있음
TransactionManager - Commit, rollBack과 같은 기능의 인터페이스
TransactionTemplate - Commit rollback을 생략해줌
AOP - 관심사를 완전히 분리

0개의 댓글