Transaction Manager
1. TransactionStatus status = transactionManager.getTransaction(new DefaultTransactionDefinition());
- 커넥션을 가져옴 (이때 내부적으로 동기화 매니저에 커넥션이 없는 경우, DataSource 에서 커넥션을 가져옴)
- 가져온 커넥션에 여러 값을 설정함 (위 코드에서는 기본 디폴트 값을 설정, 당연하게 autocommit False 처리)
- 설정이 끝난 커넥션을 트랜잭션 동기화 매니저에 바인딩함
2. 아래와 같은 service 로직을 실행하여 Repository 계층의 메서드 사용.
private void bizLogic(String fromId, String toId, int money) throws SQLException {
Member fromMember = memberRepository.findById(fromId);
Member toMember = memberRepository.findById(toId);
memberRepository.update(fromId, fromMember.getMoney() - money);
validation(toMember);
memberRepository.update(toId, toMember.getMoney() + money);
}
3. Repository 에서는 아래 코드를 통해서 트랜잭션 동기화 매니저에 저장된 커넥션(서비스로직에서 바인당한 커넥션)을 획득하여 수행.
DataSourceUtils.getConnection(dataSource);
4. 아래 코드를 통해서 마지막에 다시 동기화 매니저에 바인딩함. 직접 반환하지 않으며, 해제는 트랜잭션을 시작한 Service layer 에서 수행.
DataSourceUtils.releaseConnection(con, dataSource);
만약 트랜잭션을 사용하지 않는다면?
Service layer 에서는 그냥 서비스 로직을 호출 (트랜잭션 필요 없기 때문)
Repository 에서는 기존
DataSourceUtils.getConnection(dataSource);
코드를 호출해당 코드는 동기화 매니저에 바인딩된 객체가 없다면, 직접 DataSource 에서 커넥션을 획득
이후 직접 해당 커넥션을 통하여 로직 수행
DataSourceUtils.releaseConnection(con, dataSource)
코드로 직접 커넥션을 반환함.
transactionManager.getTransaction 가 진짜로 커넥션을 획득하나 궁금해서 확인해봄
JDBC 기준으로 PlatformTransactionManager 의 구현체인 DataSourceTrancationManger 클래스 확인
DataSourceTrancationManger 에 getTransaction 함수가 없어 부모 추상 클래스인 AbstractPlatformTransactionManager 확인
AbstractPlatformTransactionManager 안에 getTransaction 매서드 확인
해당 메서드에서 doGetTransaction() 과, isExistingTransaction(), startTransaction() 전부 실행 되는 로직이 있는 것을 확인
마지막으로 startTransaction() 에서 doBegin() 을 실행함, 해당 doBegin() 메서드의 구현체는 다시 DataSourceTrancationManger 에 있음
해당 doBegin() 메서드 안에서
Connection newCon = obtainDataSource().getConnection();
메서드 확인.
Service (@Transactional=x)
└─> PlatformTransactionManager.getTransaction(…)
├─ AbstractPlatformTransactionManager#getTransaction() ← **여기서 시작**
│ ├─ doGetTransaction() (서브클래스 구현체: DataSourceTransactionManager)
│ │ ↳ 이미 바인딩된 ConnectionHolder 조회
│ │ (새 트랜잭션이면 아직 커넥션 없음)
│ ├─ isExistingTransaction() (false → 새 트랜잭션 필요)
│ └─ startTransaction(…) ← **여기서 doBegin() 호출**
│ ├─ doBegin() (DataSourceTransactionManager)
│ │ ↳ obtainDataSource().getConnection()
│ │ → 풀(HikariCP·DBCP 등)에서 커넥션 대여
│ │ ↳ autoCommit=false, 격리수준 등 설정
│ │ ↳ ConnectionHolder ThreadLocal 바인딩
│ └─ new TransactionStatus 리턴
└─ TransactionStatus 반환
Last updated