본문 바로가기

DB

Requires_new

우리는 흔히 Requirs_new의 옵션을 생각하면 각각의 트랜잭션이 독립적으로 실행되는것으로 알고 있다. 하지만 

다음과 같은 코드가 있에서는 서비스 B에서 예외를 보냈지만 서비스 B 와 A 모두 롤백이 된다.

@RequiredArgsConstructor
@Service
public class TestServiceA {
    private final TestServiceB testServiceB;
    private final PostsRepository postsRepository;

    @Transactional
    public void save(PostsSaveRequestDto requestDto) {
        System.out.println("상위 트랜잭션 시작");
        postsRepository.save(requestDto.toEntity());
        testServiceB.save(requestDto);
    }
}

@RequiredArgsConstructor
@Service
public class TestServiceB {
    private final PostsRepository postsRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void save(PostsSaveRequestDto requestDto) {
        System.out.println("하위 트랜잭션 시작");
        postsRepository.save(requestDto.toEntity());
        throw new IllegalStateException();
    }
}

이유는 서비스 B의 예외가 A까지 전파가 되었기 때문이다. 이와 같이 트랜잭션 A와 B는 독립적이다라고 표현하기는 알맞지 않다. 하위 서비스인 B는 새로운 트랜잭션을 생성할 뿐 A의 트랜잭션과 독립적이지는 않다. 그렇다면 어떻게 이 두 트랜잭션을 독립적으로 만들 수 있을까?

@RequiredArgsConstructor
@Service
public class TestServiceA {
    private final TestServiceB testServiceB;
    private final PostsRepository postsRepository;

    @Transactional
    public void save(PostsSaveRequestDto requestDto) {
        System.out.println("상위 트랜잭션 시작");
        postsRepository.save(requestDto.toEntity());
        try {
            testServiceB.save(requestDto);
        } catch (Exception e) {
            System.out.println("하위 트랜잭션 예외");
        }
    }
}

간단하게 try catch문으로 예외를 잡아주면 하위 트랜잭션만 롤백되고 상위 트랜잭션은 커밋되어 각각의 트랜잭션이 독립적으로 실행 된다.

 

그렇다면 아래와 같은 상황에서는 어떨까? 예상데로 서비스 A 와 서비스 B의 트랜잭션이 독립적으로 실행 된다. 상위 트랜잭션만 롤백되고 하위 트랜잭션은 성공적으로 커밋된다.

@RequiredArgsConstructor
@Service
public class TestServiceA {
    private final TestServiceB testServiceB;
    private final PostsRepository postsRepository;

    @Transactional
    public void save(PostsSaveRequestDto requestDto) {
        System.out.println("상위 트랜잭션 시작");
        postsRepository.save(requestDto.toEntity());
        testServiceB.save(requestDto);
        throw new IllegalStateException();
    }
}

@RequiredArgsConstructor
@Service
public class TestServiceB {
    private final PostsRepository postsRepository;

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void save(PostsSaveRequestDto requestDto) {
        System.out.println("하위 트랜잭션 시작");
        postsRepository.save(requestDto.toEntity());
        //throw new IllegalStateException();
    }
}

결론적으로 Requires_new 옵션은 하위 트랜잭션에서 예외가 발생한다면 상위 트랜잭션까지 롤백되는 상황을 겪을 수 있는데, try catch문으로 예외발생을 잘 잡아주면, 독립적인 트랜잭션으로 실행할 수 있다.

'DB' 카테고리의 다른 글

MySQL 설치 및 DB 구축과정 미리 실습하기: DBMS 개요와 MySQL 소개  (0) 2023.08.01
정규화  (0) 2023.01.09
데이터베이스 인덱스  (0) 2023.01.07
데이터 베이스의 시작  (0) 2023.01.06
트랜잭션  (2) 2022.12.12