[Spring JPA] Transaction Manager

SeongWon Oh·2021년 10월 9일
1

Spring Framework

목록 보기
19/33
post-thumbnail

트랜잭션이란?

트렌잭션이란 데이터베이스의 상태를 변화시키기 위해 수행하는 작업의 단위 또는 한꺼번에 모두 수행되어야 할 일련의 연산들을 뜻한다.

트랜잭션이란?의 게시글을 보면 더 자세한 정보를 알 수 있습니다.

Spring Boot에서 트랜젝션 적용

  • Spring Boot에서 하나의 method를 트렌젝션으로 적용하는 방법은 method위에 @Transactional 어노테이션을 붙여주면 된다.
  • @Transactional은 java에서 제공하는 것과 Spring에서 제공하는 것이 있다.
  • @Transactional은 class위에 붙일 수도 있다. 이러한 경우 Class전체를 Transaction화 하겠다는게 아니고 class내부에 있는 각각의 method를 transaction화 하겠다는 것이다.
    method에 추가로 @Transactional을 붙이면 method에 붙은 걸 우선 적용한다.

🚨 주의할 점 1

  • Transactional내에서 개발자가 강제로 Exception을 실행시키는 코드를 넣을 때는 Checked exception인지 unchecked exception인지 확인을 해야한다.
  • Unchecked exception이 발생하면 트렌젝션 내용이 roll back이 되고 Checked exception은 트랜젝션 내에서 발생하여도 roll back되지 않고 반영이 된다❗❗
  • Checked exception이 발생하였을 때도 roll back을 시키고 싶다면 @Transactional어노테이션을 @Transactional(rollbackFor = Exception.class)와 같이 해당 exception에 rollback을 시키도록 하면 된다.

🚨 주의할 점 2

  • Transactioinal이 붙어있는 A method를 B method에서 호출하였을 때 A에서 unchecked exception이 발생하여도 rollback되지 않는다.
  • Spring Container는 Bean으로 진입할 때 달려있는 어노테이션들을 처리하도록 되어 있다.
    B라는 메서드에 진입하는 순간 container는 Bean내부로 들어왔기에 B내부에서 다른 메서드인 A를 호출 할 시 A의 메서드에 있는 어노테이션들은 무시가 된다.
  • Ex) putBookAndAuthor을 put에서 호출하여 사용하는 경우 @Transactional은 적용되지 않는다.
    public void put() {
        this.putBookAndAuthor();
    }
    @Transactional
    public void putBookAndAuthor(){
         Book book = new Book();
        book.setName("JPA 시작하기");
        bookRepository.save(book);
        Author author = new Author();
        author.setName("Seongwon");
        authorRepository.save(author);
        throw new RuntimeException("오류가 나서 DB commit이 발생하지 않았습니다.");
    }

@Transaction의 속성

Isolation

트랜잭션의 격리 수준이란 동시에 여러 트랜잭션이 처리될 때 특정 트랜잭션이 다른 트랜잭션에서 변경하거나 조회하는 데이터들을 볼 수 있도록 허용할지 말지를 결정하는 것이다.

Spring의 @Transaction의 Isolation속성은 아래와 같이 지정하면 된다.

@Transactional(isolation = Isolation.~~)
public void methodName(Long id) {
}

트랜잭션 격리 수준에 대한 자세한 정보는 트랜잭션의 격리수준에서 설명하였으니 참고하시길 바랍니다.

Isolation의 속성의 종류는 다음과 같다.

  • DEFAULT
  • READ_UNCOMMITTED
  • READ_COMMITTED
  • REPEATABLE_READ
  • SERIALIZABLE

Propagation

트랜잭션 동작 도중 다른 트랜잭션을 호출하는 상황에 선택할 수 있는 옵션이다.
Propagation속성에 따라 피호출 트랜잭션의 입장에서는 호출자의 트랜잭션을 사용할 수도 있고 새롭게 트랜잭션을 생성할 수도 있다.

Spring의 @Transaction의 Propagation속성은 아래와 같이 지정하면 된다.

@Transactional(propagation = Propagation.~~)
public void methodName(Long id) {
}
  • REQUIRED
    • default값이다.
    • 트렌젝션이 필요한데 만약에 있으면 재활용을 하고 없으면 새로 만든다. (jpa의 save메서드가 REQUIRED로 만들어져있다.)
    • REQUIRED는 하나의 트렌젝션을 여러 메서드에서 사용하기에 한 곳에서 Exception이 발생하면 전체가 Exception이 발생한다. (모두가 커밋되거나 모두가 롤백되던가!)
  • REQUIRES_NEW
    • 트렌젝션이 필요하면 기존에 존재하여도 새로 만들어서 따로 관리한다.
  • Propagation.SUPPORTS
    • 호출하는 쪽에서 Transaction이 있다면 해당 Transaction을 호출해서 사용한다.
    • REQUIRED와 다르게 호출하는 쪽에 Transaction이 없다면 굳이 Transcation을 생성하지 않고 그냥 처리한다.
  • NOT_SUPPORTED
    • 호출하는 쪽에서 Transaction이 있다면 해당 Transaction을 멈추고 transaction없이 해당 method(호출된)를 실행한다.
  • MANDATORY
    • 이미 생성된 Transaction이 무조건 있어야하며, 만약 없다면 오류를 발생시킨다.
  • NEVER
    • MANDATORY의 반대로 Transaction이 무조건 없어야하며, 만약 있다면 오류를 발생시킨다.
  • NESTED
    • REQUIRES_NEW와 비슷하나 별도의 Transaction을 생성하는게 아니라 호출하는 곳의 transaction을 사용한다.
    • 하나의 Transaction이지만 약간 분리되어서 동작한다.
    • 호출받는 곳에서 롤백이 일어나도 호출하는 곳은 다른 커밋은 안전하게 된다.
    • 반대로 호출하는 곳에서 롤백이 일어나면 호출하는 곳, 받는 곳 모두 롤백된다.


Reference

profile
블로그 이전했습니다. -> https://seongwon.dev/

0개의 댓글