Transaction

데이터베이스의 상태를 변화시키기 위해 수행(CRUD)하는 작업의 단위
데이터베이스의 데이터를 작업하다가 문제가 생겼을 경우,
이전 상태로 롤백하기 위해 사용

  • transaction 처리 명령어
    • commit : 모든 부분작업이 정상적으로 완료 -> 변경사항 한꺼번에 DB에 반영하여 마무리 됨
    • rollback : 부분작업 실패 -> 작업을 취소하고 실행 전으로 돌림


Spring이 제공하는 Transaction

AOP를 이용한 트랜잭션 분리

  • business logic code 와 transaction code 가 같이 있음
public void addUsers(List<User> userList) {
	TransactionStatus status = this.transactionManager.getTransaction(new DefaultTransactionDefinition());
	
	try {
		for (User user: userList) {
			if(isEmailNotDuplicated(user.getEmail())){
				userRepository.save(user);
			}
		}

		this.transactionManager.commit(status);
	} catch (Exception e) {
		this.transactionManager.rollback(status);
		throw e
	}
}


  • @Transactional 이용해서 코드 분리 (선언적 트랜잭션처리) -> 핵심 비지니스 로직만 남김
    • 트랜잭션코드(부가기능코드)를 클래스 밖으로 빼내서 별도의 모듈로 만듬(AOP)
      • @Transactional은 Spring의 Aop이용
      • AOP는 Dynamic Proxy 이용
      • Dynamic Proxy는 인터페이스 기반으로 동작
        => 인터페이스가 있어야만 동작함
    • DB와 관련된 트랜잭션이 필요한 Service class or method에 @Transactional 붙여주기
    • 트랜잭션 기능이 포함된 프록시 객체가 생성되어 자동으로 commit 혹은 rollback을 진행
      • @Transactional이 붙은 메서드는 메서드가 포함하고 있는 작업 중에 하나라도 실패할 경우 전체 작업을 취소
@Service
@RequiredArgsConstructor
@Transactional
public class UserService {

    private final UserRepository userRepository;

    public void addUsers(List<User> userList) {
        for (User user : userList) {
            if (isEmailNotDuplicated(user.getEmail())) {
                userRepository.save(user);
            }
        }
    }
}


@Transactional

@Transactional 붙은 클래스, 메서드 앞뒤에 프록시 생성

모든 예외상황에서 롤백 되는게 아님
기본적으로 error, unchecked exception 만 롤백
= checked exception에 대해서 롤백 안되게 설계되어 있음

=> 모든 예외에 대해서 전부 트랜잭션 롤백하고싶으면 rollbackFor={Exception.class}


  • 자바에서 예외 : error, exception
    • Error :  시스템레벨에서 발생하는 오류 -> 미리 예측불가 개발 시 신경안써도됨
    • Exception : 로직 상에서 발생하는 오류 -> 예측가능 상황에 맞게 처리
  • Checked exception, Unchecked exception - runtimeException 상속여부에 따라
    • checked exception : 컴파일부터 안됨, 예외처리코드 필수
      (IOException, SQLException)
    • unchecked exception : 런타임중 예외발생, 예외처리코드 필수아님, runtimeException 상속
      (NullPointerException, IndexOutOfBoundException)


@Transactional 옵션

1. isolation : 격리레벨

@Transactional(isolation=Isolation.DEFAULT)
public void addUser(User user) throws Exception {
  • DEFAULT : 기본
  • READ_UNCOMMITED (level 0) : 커밋되지 않는 데이터에 대한 읽기를 허용
  • READ_COMMITED (level 1) : 커밋된 데이터에 대해 읽기 허용
  • REPEATEABLE_READ (level 2) : 동일 필드에 대해 다중 접근 시 모두 동일한 결과를 보장
  • SERIALIZABLE (level 3) : 가장 높은 격리, 성능 저하의 우려가 있음


2. propagation : 전파속성

@Transactional(propagation=Propagation.REQUIRED)
public void addUser(User user) throws Exception {


제목 없음

  • REQUIRED : default
    • 진행중인 트랜잭션이 있다면 해당 트랜잭션 속성 따름
    • 진행중이 아니라면 새로운 트랜잭션 생성


제목 없음

  • REQUIRES_NEW : 항상 새로운 트랜잭션 생성
    • 진행중인 트랜잭션이 있다면 잠깐 보류
    • 해당 트랜잭션 작업 먼저 진행


제목 없음

  • MANDATORY
    • 진행중인 트랜잭션이 있어야만 작업수행
    • 없으면 Exception 발생


제목 없음

  • NEVER
    • 진행중인 트랜잭션 있으면 Exception
    • 진행중이지 않을 때만 작업수행


제목 없음

  • NESTED
    • 진행중인 트랜잭션 있으면 중첩된 트랜잭션 실행
    • 없으면 REQUIRED와 동일하게 실행
  • SUPPORT
    • 진행중인 트랜잭션이 있다면 해당 트랜잭션 속성 따름
    • 없다면 트랜잭션 없이 작업수행
  • NOT_SUPPORT
    • 진행중인 트랜잭션 있다면 보류, 트랜잭션 없이 작업수행


3. noRollbackFor : 예외무시

특정예외 발생 시 rollback처리 하지 않음

@Transactional(noRollbackFor=Exception.class)
public void addUser(User user) throws Exception {


4. rollbackFor : 예외추가

특정예외 발생 시 강제로 rollback

@Transactional(rollbackFor=Exception.class)
public void addUser(User user) throws Exception {


5. timeout : 시간지정

지정한 시간 내에 해당 메소드수행이 완료되지 않을경우 rollback
default : -1 (no timeout)

@Transactional(timeout=10)
public void addUser(User user) throws Exception {


6. readOnly : 읽기전용

default : false
true 시 insert, update, delete 실행 시 예외발생 = select만 가능

@Transactional(readonly = true)
public void addUser(User user) throws Exception {


Test method + @Transactional

메서드 종료될 때 자동으로 롤백됨

  • Auto Increment 옵션으로 인해 증가한 id는 rollback되어도 감소되지 않음
    • Auto Increment 옵션은 트랜잭션 범위 밖에서 동작



Reference
https://mangkyu.tistory.com/154
https://velog.io/@kdhyo/JavaTransactional-Annotation-%EC%95%8C%EA%B3%A0-%EC%93%B0%EC%9E%90-26her30h
토비의스프링(저자:이일민)
https://deveric.tistory.com/86

업데이트: