스프링에서는 어떻게 트랜잭션을 처리할 수 있을까?
스프링은 @Transactional
어노테이션을 선언하여 사용하는 선언적 트랜잭션을 제공한다.
@Transactional
을 사용하는 경우와 방법에 대해 간단하게 정리하고자 한다.
우선 트랜잭션의 의미에 대해 알아야 한다.
트랜잭션이란 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위이다.
이때 작업의 단위는 질의어 한 문장이 아닌 사람이 정하는 기준에 따라 정해진다.
예를 들자.
고객이 상품을 구매를 할때 어떤 동작이 일어날까?
- 고객이 상품을 구매한다.
- 고객의 구매 내역에 해당 상품이 추가된다.
- 상품의 보유 개수를 수정한다.
이 과정을 하나의 트랜잭션으로 들 수 있다.
만약에 상품의 보유 개수를 수정하는 과정에서 오류가 나면 어떻게 될까?
고객의 구매 내역에 상품이 추가됬으나 상품의 보유 개수는 수정되지 않는 상황이 일어날 수 있다.
이런 경우를 방지하기 위해 트랜잭션을 이용해 오류가 발생한 경우 모든 동작을 취소할 수 있다.
@Transactional
을 사용하여 트랜잭션을 사용할 수 있다.
@Transactional()
public void save() {
...
}
해당 방식을 사용하면 더 편하고 쉽게 트랜잭션을 처리할 수 있으며, 트랜잭션 전파와 같은 요소를 자동으로 처리해준다는 장점이 있다.
참고로, 트랜잭션에 포함된 INSERT 작업으로 증가된 ID 값은 롤백되어도 감소하지 않는다.
@Transactional
은 다양한 옵션을 제공한다.
isolation
트랜잭션의 격리 수준을 정한다.
여러 트랜잭션이 동시에 처리될 때 다른 트랜잭션에서 변경 또는 조회하는 데이터의 읽기에 대한 허용 여부를 결정한다.
@Transactional(isolation = Isolation.DEFAULT)
propagation
전파 옵션을 정한다.
트랜잭션 처리 중 다른 트랜잭션을 호출 할 때 어떻게 할지 정한다.
@Transactional(propagation = Propagation.REQUIRED)
noRollbackFor
특정 예외 발생 시, 롤백 되지 않도록 한다.
@Transactional(noRollbackFor = Exception.class)
rollbackFor
특정 예외 발생 시, 롤백 되도록 한다.
@Transactional(rollbackFor = Exception.class)
timeout
지정 시간 내에 작업이 완료되지 않으면 롤백한다.
@Transactional(timeout = 2) // -1로 할 경우 사용하지 않음
readOnly
트랜잭션을 읽기 전용으로 설정한다.
INSERT, UPDATE, DELETE 를 실행하면 예외가 발생한다.
@Transactional(readOnly = true)
각 옵션에 대한 설정 값은 구글 검색을 통해 쉽게 찾을 수 있다.
자신이 정한 조건에 맞지 않아 강제로 롤백 시켜야 할 경우가 있다.
이때는 예외를 발생시키면 된다.
if(code != 'A') {
throw new RuntimeException("예외 발생");
}
reference
https://mommoo.tistory.com/62
https://scshim.tistory.com/528