깔끔하게 정리된 코드로 트랜잭션 경계를 관리하기 위해 스프링이 제공하는 방법
Connection을 파라미터로 직접 전달하는 문제를 해결해보자.
upgradeLevels()
메서드가 트랜잭션 경계 설정을 해야 한다는 사실은 피할 수 없다.
upgradeLevels()
메서드에서 Connection 생성과 트랜잭션 경계를 관리하게 한다.
(스프링 사용 전) DAO 를 호출할 때 Connection 을 파라미터로 넘겨준다.
(스프링 사용 후) 트랜잭션 동기화transaction symchronization
트랜잭션 동기화를 사용한 경우의 작업 흐름
.setAutoCommit(false)
** 를 호출해 트랜잭션을 시작한다.update()
메서드가 호출된다update()
호출된다.commit()
을 호출해서 트랜잭션을 완료한다.어느 작업중에라도 예외 상황 발생 시 UserService 는 Connection**
.rollback()
** 을 호출하고 Connection 오브젝트는 제거한다.
<aside> 📌
트랜잭션 동기화 저장소는 작업 스레드마다 독립적으로 Connectino 오브젝트를 저장하고 관리한다. 고로 다중 사용자를 처리하는 서버의 멀티스레드 환경에서 충돌날 일은 없다.
</aside>
멀티스레드 환경에서도 안전한 트랜잭션 동기화 방법 구현은 기술적으로 어려운 일이다.
→ 스프링은 JdbcTemplate 과 더불어 트랜잭션 동기화 기능을 지원하는 유틸리티 메서드를 제공한다.
public class UserService {
private DataSource dataSource;
public void setDataSource(DataSource dataSource){
this.dataSource = dataSource;
}
// UserService.class
public void upgradeLevels(){
**TransactionSynchronizationManager.initSynchronization();;**
Connection c = **DataSourceUtils.getConnection(dataSource);**
c.setAutoCommit(false);