수동 JPA 트랜잭션 대 선언적 @Transactional
장황한 begin/commit/rollback 블록을 단일 @Transactional 어노테이션으로 대체합니다.
코드 비교
✕ Java EE
@PersistenceContext
EntityManager em;
public void transferFunds(Long from, Long to,
BigDecimal amount) {
EntityTransaction tx = em.getTransaction();
tx.begin();
try {
Account src = em.find(Account.class, from);
Account dst = em.find(Account.class, to);
src.debit(amount);
dst.credit(amount);
tx.commit();
} catch (Exception e) {
tx.rollback();
throw e;
}
}
✓ Jakarta EE 8+
@ApplicationScoped
public class AccountService {
@PersistenceContext
EntityManager em;
@Transactional
public void transferFunds(Long from, Long to,
BigDecimal amount) {
var src = em.find(Account.class, from);
var dst = em.find(Account.class, to);
src.debit(amount);
dst.credit(amount);
}
}
이 코드에 문제가 있나요? 알려주세요.
모던 방식이 더 나은 이유
보일러플레이트 없음
하나의 어노테이션이 반복적인 begin/commit/rollback try-catch 블록을 대체합니다.
더 안전한 롤백
컨테이너는 확인되지 않은 예외에서 롤백을 보장합니다 — catch 블록을 잊을 위험이 없습니다.
선언적 제어
전파, 격리, 롤백 규칙이 어노테이션 속성으로 표현됩니다.
이전 방식
수동 트랜잭션
모던 방식
@Transactional
JDK 버전
11
난이도
중급
JDK 지원
수동 JPA 트랜잭션 대 선언적 @Transactional
사용 가능
Jakarta EE 8 / Java 11 이후 널리 사용 가능
동작 원리
수동 트랜잭션 관리는 명시적 begin(), commit(), rollback() 호출과 오류 처리가 필요합니다. @Transactional은 컨테이너가 경계를 관리하도록 하여 비즈니스 코드가 일관성에 집중할 수 있게 합니다.
관련 문서