데이터베이스에서 여러 개의 작업(작은 작업 단위들)이 있을 때, 이 작섭들을 하나의 작업처럼 묶어서 처리하는 개념.
즉, 부분적으로 완료되는 상태를 허용하지 않음.
트랜잭션은 은행에서 송금하는 경우와 같다.
계좌 A에서 계좌 B로 10만원 송금을 한다면:
① A에서 10만원 차감
② B에서 10만원 증가
이 두 과정은 반드시 하나로 묶여야 한다.
정상적인 경우:
A 계좌에서 10만원 빠지고, B 계좌에 10만원이 들어갑니다.
문제가 생긴 경우 (예: 중간에 시스템 오류):
만약 A 계좌에서만 돈이 빠지고 B에 돈이 안 들어가면
따라서 이 두 가지 작업을 하나의 트랜잭션 으로 관리하여,
문제가 발생했을 때는 모든 작업을 없던 일로 되돌립니다.
트랜잭션의 특성을 설명하는 용어로 ACID라는 개념이 있습니다.
스프링에서는 @Transactional 어노테이션을 통해 쉽게 관리할 수 있음.
@Service
public class OrderService {
@Transactional
public void orderProduct(Long userId, Long productId, int quantity) {
// ① 재고를 줄이고
productRepository.decreaseStock(productId, quantity);
// ② 주문 내역을 생성한다
orderRepository.createOrder(userId, productId, quantity);
// 여기서 오류가 발생하면 위 두 작업이 전부 원상복구됩니다.
}
}
모든 메서드에 무작정 @Transactional을 붙이면 안 됨.
읽기 전용(조회) 메서드에는 명시적으로 readOnly=true 옵션을 줄 수 있음.
@Transactional(readOnly = true)
public User findUser(Long id) {
return userRepository.findById(id).orElse(null);
}