우주먼지
article thumbnail
Published 2022. 11. 4. 20:08
선언형 트랜잭션 Framework/Spring

💡 Transaction

 

 

 

ACID 원칙

  • 1. 원자성 (Atomicity)
    • All or Nothing 보장
  • 2. 일관성 (Consistency)
    • 어떤 값 증가시 연관된 값 일관성있게 증가
  • 3. 격리성 (Isolation)
    • 각 트랜잭션 당 각각 독립적 실행
  • 4. 지속성 (Durability)
    • 트랜잭션 완료 후 결과 지속 보장

 

트랜잭션 커밋 & 롤백

  • Commit
    • 완료된 작업 최종 DB 반영 - 트랜잭션 종료
  • RollBack
    • 작업중 문제 발생 시 수행작업 취소 -> 원상태 복귀
  • 조회 메소드에는 @Transaction의 Attr을 readOnly=true 로 설정함으로써 성능 최적화 과정을 거치도록 한다

 

트랜잭션 전파 (Transaction Propagation)

  • @Transactional의Attribute
    • Propagation.REQUIRED
      • Default 값, 진행중 트랜잭션이 있으면 해당 트랜잭션 참여, 없으면 새로 생성
    • Propagation.REQUIRED_NEW
      • 진행중인 트랜잭션과 별개로 새로운 트랜잭선 생성, 기존 트랜잭션은 이 트랜잭션이 끝날때까지 terminate
    • Propagation.MANDATORY
      • 진행중 트랜잭션이 없으면 예외를 발생시킴
    • Propagation.NOT_SUPPORTED
      • 트랜잭션을 필요로 하지 않음, 메소드 실행시 진행중 트랜잭션 중지, 메소드 종료시 진행중 트랜잭션 이어서 실행
    • Propagation.NEVER
      • 트랜잭션을 필요로 하지 않음, 트랜잭션 진행 중일시, 예외를 발생시킴

 

트랜잭션 격리 레벨 (트랜잭션 격리성 조정 옵션)

  • Isolation.DEFAULT
    • 기본값
  • Isolation.READ_UNCOMMITTED
    • 다른 트랜잭션에서 커밋하지 않은 데이터 읽기 허용
  • Isolation.READ_COMMITTED
    • 다른 트랜잭션에서 커밋된 데이터 읽기 허용
  • Isolation.REPEATABLE_READ
    • 트랜잭션의 조회된 데이터를 계속 조회해도 같은 데이터가 조회되도록 보장
  • Isolation.SERIALIZABLE
    • 동일 데이터에 동시에 여러개의 트랜잭션이 수행되지 않게 함

 

 

체크 예외

  • @Transactional의 Attribute로 rollbackFor 옵션을 사용해서 해당 체크예외를 직접 지정하거나
    unchecked exception으로 감싸야 rollback 기능 적용 가능

💡 AOP 방식 트랜잭션 구현

 

package com.returns.aop;

import org.springframework.aop.Advisor;
import org.springframework.aop.aspectj.AspectJExpressionPointcut;
import org.springframework.aop.support.DefaultPointcutAdvisor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.transaction.TransactionDefinition;
import org.springframework.transaction.interceptor.NameMatchTransactionAttributeSource;
import org.springframework.transaction.interceptor.RuleBasedTransactionAttribute;
import org.springframework.transaction.interceptor.TransactionAttribute;
import org.springframework.transaction.interceptor.TransactionInterceptor;

import javax.transaction.TransactionManager;
import java.util.HashMap;
import java.util.Map;

@Configuration
public class TxAdvisor {

    private final TransactionManager transactionManager;

    public TxAdvisor(@SuppressWarnings("SpringJavaInjectionPointsAutowiringInspection") TransactionManager transactionManager) {
        this.transactionManager = transactionManager;
    }

    @Bean
    public TransactionInterceptor txAdvice() {

        //i 메소드 이름 패턴에 따른 구분 적용
        NameMatchTransactionAttributeSource txAttributeSource = new NameMatchTransactionAttributeSource();

        //i 조회 메소드를 제외한 공통 트랜잭션 Attribute
        RuleBasedTransactionAttribute txAttribute = new RuleBasedTransactionAttribute();
        txAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);

        //i 조회 메소드에 적용하기 위한 트랜잭션 Attribute
        RuleBasedTransactionAttribute txFindAttribute = new RuleBasedTransactionAttribute();
        txFindAttribute.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED);
        txFindAttribute.setReadOnly(true);

        //i 설정한 트랜잭션 Attribute를 Map에 추가, Map의 키를 '메소드 이름 패턴' 으로 지정해서 각각의 트랜잭션 Attribute 추가
        Map<String, TransactionAttribute> txMethods = new HashMap<>();
        txMethods.put("find*", txFindAttribute);
        txMethods.put("*", txAttribute);

        //i 트랜잭션 Attribute를 추가한 Map 객체를 Source로 넘겨줌
        txAttributeSource.setNameMap(txMethods);

        //i TransactionInterceptor의 생성자 파라미터로 TransactionManager, txAttributeSource 전달
        return new TransactionInterceptor((org.springframework.transaction.TransactionManager) transactionManager, txAttributeSource);
    }

    @Bean
    public Advisor txAd() {
        AspectJExpressionPointcut pointcut = new AspectJExpressionPointcut();
        pointcut.setExpression("execution(* com.returns.coffee.service." + "CoffeeService.*(..))");

        return new DefaultPointcutAdvisor(pointcut, txAdvice());
    }
}

 

'Framework > Spring' 카테고리의 다른 글

Testing (Mockito)  (0) 2022.11.08
분산 트랜잭션  (0) 2022.11.08
JPA & Hibernate (Java Persistence API)  (0) 2022.11.01
Spring Data JDBC 기반 도메인 엔티티 & 테이블 설계  (0) 2022.10.27
Spring JDBC  (0) 2022.10.27
profile

우주먼지

@o귤o

포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!

검색 태그