1. 트랜잭션 매니저와 리소스의 연관성
- 트랜잭션 매니저는 특정 리소스와 연결되어 있음 (Database connection, Hibernate session)
- 트랜잭션 매니저는 자신과 연결된 리소스를 사용해서 트랜잭션을 제어하고 자동으로 관리함 (생성 - 재사용 - 정리)
2. Transaction Synchronization
- 트랜잭션 시작과 종료 시점에 여러 리소스들을 함께 연결되도록 하는 역할
- 트랜잭션 컨텍스트에 묶어서 리소스들을 함께 연결시킴
동작 순서
단계 | 설명 |
트랜잭션 시작 |
ThreadLocal에 트랜잭션 컨텍스트 생성
리소스들을 트랜잭션 컨텍스트에 연결 |
트랜잭션 도중 |
컨텍스트 내의 리소스를 재사용하며 작업 수행
|
트랜잭션 종료 |
리소스들을 커밋 또는 롤백
ThreadLocal에서 컨텍스트 해제 |
예제) EntityManager
더보기
@Transactional
public void service() {
// 트랜잭션 시작됨 → 트랜잭션 컨텍스트 생성
// EntityManager 생성되고 컨텍스트에 등록됨
EntityManager em1 = entityManagerFactory.createEntityManager();
// 같은 트랜잭션 범위 내에서 다른 DAO나 서비스도 이 EntityManager를 재사용함
dao.doSomething(); // 여기서도 같은 em1 사용
// 작업 후 트랜잭션 커밋 → em1도 정리됨
}
실제 도구들
도구 | 역할 |
TransactionSynchronization |
리소스들이 트랜잭션과 동기화되도록 콜백 인터페이스 제공
|
AbstractPlatformTransactionManager |
위의 동기화 메커니즘을 내부적으로 제어 |
TransactionSynchronizationManager |
스레드별로 트랜잭션 컨텍스트 관리 (바인딩)
|
3. High-level Synchronization Approach
접근 방식 | 설명 | 주요 예시 API |
Template-based API | 데이터 접근 과정을 자동으로 처리 | JdbcTemplate HibernateTemplate |
Transaction-aware Proxy | 리소스를 트랜잭션 컨텍스트에 등록 및 동기화 | EntityManagerProxy DataSourceProxy |
ORM API 연동 | ORM에게 Transaction-aware Proxy에서 제공하는 리소스를 연결 | EntityManager |
예제) JdbcTemplate
더보기
@Repository
public class UserRepository {
private final JdbcTemplate jdbcTemplate;
public UserRepository(DataSource dataSource) {
this.jdbcTemplate = new JdbcTemplate(dataSource);
}
public List<User> findAllUsers() {
String sql = "SELECT * FROM users";
return jdbcTemplate.query(sql, new UserRowMapper());
}
public void saveUser(User user) {
String sql = "INSERT INTO users (name, email) VALUES (?, ?)";
jdbcTemplate.update(sql, user.getName(), user.getEmail());
}
private static class UserRowMapper implements RowMapper<User> {
@Override
public User mapRow(ResultSet rs, int rowNum) throws SQLException {
User user = new User();
user.setId(rs.getLong("id"));
user.setName(rs.getString("name"));
user.setEmail(rs.getString("email"));
return user;
}
}
}
예제) EntityManagerProxy + EntityManager
더보기
@Service
public class OrderService {
@PersistenceContext
private EntityManager entityManager; // EntityManagerProxy가 주입됨
@Transactional
public void placeOrder(Order order) {
entityManager.persist(order);
// 다른 비즈니스 로직...
}
}
4. Low-level Synchronization Approach
- Spring의 유틸리티 클래스를 사용하여, 애플리케이션 코드가 직접 Native Persistence API의 리소스를 다루도록 하는 방식
유틸 클래스 | 사용 대상 | 동작 요약 |
DataSourceUtils | JDBC |
현재 트랜잭션에 참여된 커넥션을 반환.
없으면 새로 생성하고 트랜잭션에 동기화 |
EntityManagerFactoryUtils | JPA | 트랜잭션에 바인딩된 EntityManager를 반환. 없으면 예외 |
SessionFactoryUtils | Hibernate | 트랜잭션에 바인딩된 Hibernate Session 반환. 필요 시 새로 열기도 가능 |
예외) DataSourceUtils
더보기
DataSourceUtils.getConnection(datasource)
- Spring의 예외 처리 구조로 변환됨 (일관성)
- SQLException을 CannotGetJdbcConnectionException으로 변환
예외) EntityManagerFactoryUtils
더보기
public class JpaRepository {
private final EntityManagerFactory emf;
public JpaRepository(EntityManagerFactory emf) {
this.emf = emf;
}
public void save(Member member) {
EntityManager em = EntityManagerFactoryUtils.getTransactionalEntityManager(emf);
em.persist(member); // 트랜잭션 바운드 EntityManager 사용
}
}
예외) SessionFactoryUtils
더보기
public class HibernateRepository {
private final SessionFactory sessionFactory;
public HibernateRepository(SessionFactory sessionFactory) {
this.sessionFactory = sessionFactory;
}
public void save(Member member) {
Session session = SessionFactoryUtils.getSession(sessionFactory, true); // 트랜잭션 바운드 Session
session.save(member);
}
}
출처