예를 들어
1. 주문기록을 저장하고
2. 포인트를 적립시키고
3. 결제 기록을 저장하는 코드가 있다고 해보자
그러면 주문 기록은 잘 저장이 됐는데, 포인트가 적립이 되지 않았다면, 결제 기록이 저장되지 않는다. 하지만, 고객은 주문 기록이 보이니까 주문이 됐는데 왜 포인트가 적립되지 않았냐고 얘기할 수 있다. 이런 상황을 피하기 위해, 한 메소드 내에서의 작업이 모든 SQL을 성공시키거나 하나라도 실패하면 모두 실패시키는 것을 트랜잭션 이라고 한다. 쪼갤 수 없는 업무의 최소 단위이기도 한다.
start transaction
commit;
rollback;
Service 메소드가 시작할 때 트랜잭션이 시작되고, Service 메소드 로직이 모두 정상적으로 성공하면 commit되고, Service 메소드 로직 실행 도중 문제가 생기면 rollback 되는 것이다.
스프링에서는 트랜잭션을 @Transactional을 사용해서 쉽게 적용시킬 수 있다. Service 메소드를 찾아 그위에 @Transactional을 붙인다. org.springframework.transaction에서의 Transactional 어노테이션을 붙인다. 이렇게 하면 복잡하게 start transaction, commit, rollback 등을 안해도 되고, 알아서 트랜잭션이 적용된다.
이때, SELECT 쿼리만 사용한다면, readOnly 옵션을 붙일 수 있는데, 이때는 CRUD 등에서의 데이터 변경을 위한 불필요한 기능이 빠지기 때문에 약간의 성능적 이점이 생긴다.
@Transactional은 IOException과 같은 Checked Exception은 rollback이 일어나지 않는다.
테이블과 매핑된 Entity 객체를 관리/보관하는 역할이다. 잘 감이 오지 않는다면, 이것만 기억하자. 스프링에서는 트랜잭션을 사용하면 영속성 컨텍스트가 생겨나고, 트랜잭션이 종료되면 영속성 컨텍스트가 종료된다.