- 로컬 트랜잭션 / 분산 트랜잭션
- Spring에서 사용되는 트랜잭션 방식은 선언형 / 프로그래밍 코드 베이스 방식
- 트랜잭션은 부가 기능 AOP의 적용 대상 중 하나
- 애너테이션 방식의 트랜잭션 적용
✔ 클래스 레벨에@Transactional
적용
✔ rollback 동작 유무 확인
- 회원 정보를 저장하고 메서드가 종료되기 전에 강제로 런타임예외 발생시키기
체크 예외는 rollback이 잘 될까?
캐치 한 후에 해당 예외를 복구할지 회피할지 등의 예외 전략 고민해야함.
예외 전략을 짤 필요 없다면@Transactional(rollbackFor={SQLException.class, DataFormatException.class})
와 같이 직접 지정해주거나 언체크 예외로 감싸서 rollback이 동작하도록 할 수 있다.✔ 메서드 레벨에
@Transactional
적용
- 읽기 전용 트랜잭션이 적용됨.
- 조회 메서드에
@Transactional(readOnly = true)
로 설정하는 이유
findMember()
와 같은 조회 메서드에 읽기전용으로 설정해도 commit 절차를 진행하긴한다.
읽기 전용으로 설정하면 JPA 내부적으로 영속성 컨텍스트를 flush 하지 않음.
변경 감지를 위한 스냅샷 생성도 진행하지 않는다.
(성능 최적화)✔ 클래스 레벨과 메서드 레벨의 트랜잭션 적용 순서
- 클래스 레벨에만
@Transactional
이 적용된 경우
- 클래스 레벨의 @Transactional 애너테이션이 메서드에 일괄 적용
- 클래스 레벨과 메서드 레벨에 함께 적용된 경우
- 메서드 레벨의
@Transactional
애너테이션이 적용됨.- 메서드 레벨에 애너테이션이 적용되지 않았을 경우, 클래스 레벨의
@Transactional
애너테이션이 적용된다.
Propagation.REQUIRED
를 지정하면 메서드 실행 시, 현재 진행 중인 트랜잭션이 존재하면 해당 트랜잭션을 사용하고, 존재하지 않으면 새 트랜잭션을 생성하도록 해준다.createOrder()
메서드를 호출하면 트랜잭션이 하나 생성, createOrder()
메서드 내에서 updateMember()
메서드를 호출하면 현재 OrderService에서 진행중인 트랜잭션에 참여
- 트랜잭션 전파 (Transaction Propagation)
- 트랜잭션의 경계에서 진행 중인 트랜잭션이 존재할 때 또는 존재하지 않을 때, 어떻게 동작할 것인지 결정하는 방식
Propagation.REQUIRED
(디폴트)
진행중인 트랜잭션이 없으면 새로 시작하고, 진행 중인 트랜잭션이 있으면 해당 트랜잭션에 참여Propagation.REQUIRES_NEW
이미 진행중인 트랜잭션과 무관하게 새로운 트랜잭션 시작, 기존 진행중은 새로 시작된 트랜잭션이 종료할 때까지 중지됨.Propagation.MANDATORY
진행중인 트랜잭션이 없으면 예외를 발생시킴.Propagation.*NEVER*
트랜잭션을 필요로 하지 않음, 진행 중인 트랜잭션이 존재할 경우에는 예외 발생- 트랜잭션 격리 레벨 (Isolation Level)
- 결리성을 조정할 수 있는 옵션
Isolation.DEFAULT
데이터베이스에서 제공하는 기본 값Isolation.READ_UNCOMMITTED
다른 트랜잭션에서 커밋하지 않은 데이터를 읽는 것을 허용Isolation.READ_COMMITTED
다른 트랜잭션에 의해 커밋된 데이터를 읽는 것을 허용Isolation.REPEATABLE_READ
트랜잭션 내에서 한 번 조회한 데이터를 반복해서 조회해도 같은 데이터가 조회되게 함.Isolation.SERIALIZABLE
동일한 데이터에 대해서 동시에 두 개 이상의 트랜잭션이 수행되지 못하도록 함.
TransactionManager
DITransactionInterceptor
빈 등록TransactionInterceptor
를 이용해서 대상 클래스 또는 인터페이스에 트랜잭션 경계를 설정하고 적용메서드 이름 패턴
으로 지정해서 각각의 트랜잭션 애트리뷰트를 추가TransactionIntercepter
객체 생성참고 : https://shinsunyoung.tistory.com/88