트랜 잭션 관리 방법
1.
선언 방식 - @Transactional
2.
프로그래밍 방식 - PlatformTransactionManager or TransactionaTemplate를 통한 트랜잭션 관련 코드 작성
@Transaction AOP 전체 흐름
1.
사용자가 @Transactional이 붙은 메서드를 호출하면 AOP가 적용된 CGLIB 프록시 호출
2.
트랜잭션이 시작되고 스프링부트가 자동으로 등록시킨 PlatFormTransactionManager를 스프링 컨테이너로부터 획득 - getTransaction()
3.
데이터소스와 커넥션을 생성하고 TransactionSynchronizationManager 에 커넥션을 보관
4.
프록시가 실제 비즈니스 로직 호출
5.
비즈니스 로직 내 데이터소스와 연동할 때 TransactionSynchronizationManager 로부터 보관한 커넥션 획득
트랜잭션 매니저(PlatFormTransactionManager )하는 역할
•
트랜잭션 추상화
◦
데이터 접근 기술(JDBC, JPA 등)에 따라 트랜잭션을 사용하는 코드 상이해 트랜잭션 기능을 추상화한 것이 PlatFormTransactionManager 인터페이스
◦
따라서 데이터 접근 기술에 따른 트랜잭션 구현체를 가져다 쓰면 됨
package org.springframework.transaction;
import org.springframework.lang.Nullable;
public interface PlatformTransactionManager extends TransactionManager {
TransactionStatus getTransaction(@Nullable TransactionDefinition definition)
throws TransactionException;
void commit(TransactionStatus status) throws TransactionException;
void rollback(TransactionStatus status) throws TransactionException;
}
Java
복사
▪
getTransaction() - 트랜잭션 시작 or 기존에 이미 진행 중인 트랜잭션이 있는 경우 해당 트랜잭션에 참여
•
리소스 동기화
→ 커넥션을 보관하고, ThreadLocal을 사용해 커넥션을 동기화시켜 멀티 스레드 환경에서도 안전하게 커넥션 획득 가능하게 함
public abstract class TransactionSynchronizationManager {
private static final ThreadLocal<Map<Object, Object>> resources =
new NamedThreadLocal<>("Transactional resources");
private static final ThreadLocal<Set<TransactionSynchronization>> synchronizations =
new NamedThreadLocal<>("Transaction synchronizations");
private static final ThreadLocal<String> currentTransactionName =
new NamedThreadLocal<>("Current transaction name");
private static final ThreadLocal<Boolean> currentTransactionReadOnly =
new NamedThreadLocal<>("Current transaction read-only status");
private static final ThreadLocal<Integer> currentTransactionIsolationLevel =
new NamedThreadLocal<>("Current transaction isolation level");
private static final ThreadLocal<Boolean> actualTransactionActive =
new NamedThreadLocal<>("Actual transaction active");
// 중략
@Nullable
public static Object getResource(Object key) {
Object actualKey = TransactionSynchronizationUtils.unwrapResourceIfNecessary(key);
return doGetResource(actualKey);
}
// 중략
}
Java
복사
결론
1.
트랜잭션 어노테이션을 통해 트랜잭션 시작
2.
트랜잭션 매니저(PlatFormTransactionManager )를 불러와 데이터소스 커넥션을 생성
3.
트랜잭션 동기화 매니저(TransactionSynchronizationManager )에 커넥션 보관
4.
프록시에서 실제 비즈니스 로직을 호출할 시점에 DB와 연동하는 과정 속에서 3의 트랜잭션 동기화 매니저로부터 동일 커넥션을 획득하여 트랜잭션 진행