1. 💡 Transaction

1.1. ACID 원칙
- 1. 원자성 (Atomicity)
- All or Nothing 보장
- 2. 일관성 (Consistency)
- 어떤 값 증가시 연관된 값 일관성있게 증가
- 3. 격리성 (Isolation)
- 각 트랜잭션 당 각각 독립적 실행
- 4. 지속성 (Durability)
- 트랜잭션 완료 후 결과 지속 보장
1.2. 트랜잭션 커밋 & 롤백
- Commit
- 완료된 작업 최종 DB 반영 - 트랜잭션 종료
- RollBack
- 작업중 문제 발생 시 수행작업 취소 -> 원상태 복귀
- 조회 메소드에는 @Transaction의 Attr을 readOnly=true 로 설정함으로써 성능 최적화 과정을 거치도록 한다
1.3. 트랜잭션 전파 (Transaction Propagation)
- @Transactional의Attribute
- Propagation.REQUIRED
- Default 값, 진행중 트랜잭션이 있으면 해당 트랜잭션 참여, 없으면 새로 생성
- Propagation.REQUIRED_NEW
- 진행중인 트랜잭션과 별개로 새로운 트랜잭선 생성, 기존 트랜잭션은 이 트랜잭션이 끝날때까지 terminate
- Propagation.MANDATORY
- 진행중 트랜잭션이 없으면 예외를 발생시킴
- Propagation.NOT_SUPPORTED
- 트랜잭션을 필요로 하지 않음, 메소드 실행시 진행중 트랜잭션 중지, 메소드 종료시 진행중 트랜잭션 이어서 실행
- Propagation.NEVER
- 트랜잭션을 필요로 하지 않음, 트랜잭션 진행 중일시, 예외를 발생시킴
- Propagation.REQUIRED
1.4. 트랜잭션 격리 레벨 (트랜잭션 격리성 조정 옵션)
- Isolation.DEFAULT
- 기본값
- Isolation.READ_UNCOMMITTED
- 다른 트랜잭션에서 커밋하지 않은 데이터 읽기 허용
- Isolation.READ_COMMITTED
- 다른 트랜잭션에서 커밋된 데이터 읽기 허용
- Isolation.REPEATABLE_READ
- 트랜잭션의 조회된 데이터를 계속 조회해도 같은 데이터가 조회되도록 보장
- Isolation.SERIALIZABLE
- 동일 데이터에 동시에 여러개의 트랜잭션이 수행되지 않게 함
1.5. 체크 예외
- @Transactional의 Attribute로 rollbackFor 옵션을 사용해서 해당 체크예외를 직접 지정하거나
unchecked exception으로 감싸야 rollback 기능 적용 가능
2. 💡 AOP 방식 트랜잭션 구현
<java />
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 |