SpringBoot에서 트랜잭션 처리를 구현합시다.

16219 단어 SpringBoot
트랜잭션 처리를 구현해 봅시다.
SpringBoot에서는 어떻게 해야 할까요?

트랜잭션 처리는 @Transactional 어노테이션에서



예를 들면 이런 느낌의 구현시, insert 처리에 대해서 트랜잭션을 걸고 싶다고 합니다.
(만약 전부의 소스 코드 같은 분은 마지막 분에 gitlab의 URL 붙이고 있으므로 그쪽으로부터 부디)
// IndexController.java

@Controller
public class IndexController {

  :

  @RequestMapping
    public String index(Model model) {
    // do something,
  }

  @RequestMapping(value = "/insert")
  public String insert(Model model, @RequestParam("name") String name) {
    // do something.
  }

  :
}

아래와 같이 insert 메소드의 전에 @Transactional 어노테이션을 추가하기만 하면 됩니다.

아, import org.springframework.transaction.annotation.Transactional; 도 필요하네요.
// IndexController.java

import org.springframework.transaction.annotation.Transactional; // ←これと

@Controller
public class IndexController {

  :

  @RequestMapping
    public String index(Model model) {
    // do something,
  }

  @Transactional // ← これを追加!
  @RequestMapping(value = "/insert")
  public String insert(Model model, @RequestParam("name") String name) {
    // do something.
  }

  :
}

이것으로 insert 메소드중의 실행중에 예외가 발생하면 자동적으로 롤백을 해 줍니다. 간단하네요.

뭔가 조심하는 것은 있을까.

롤백하지 않는 예외가 있습니다.



다만, 롤백의 주의점으로서, 비검사 예외(RuntimeException 및 그 서브 클래스)가 발생했을 경우는 롤백되지만, 검사 예외(Exception 및 그 서브 클래스로 RuntimeException의 서브 클래스가 아닌 것)가 발생했을 경우는 롤 백되지 않고 커밋된다.

via : Spring에서 트랜잭션 관리

글쎄. 시도해 봅시다. 예외를 제어하기 쉽기 때문에 update 처리에 예외 처리를 넣을 수 있습니다. 데모 페이지의 과일 이름 바꾸기 > 변경 후 텍스트 영역에 非検査例外 , 検査例外를 입력하면 각 예외를 throw하는 프로세스가 추가되었습니다.


// IndexController.java

@Controller
public class IndexController {

  :

  @Transactional
    @RequestMapping(value = "/update")
    public String insert(Model model, @RequestParam("chg_before_name") String before_name,
            @RequestParam("chg_after_name") String after_name) throws Exception {

        fruitMapper.update(before_name, after_name);

        List<Fruit> list = fruitMapper.selectAll();
        model.addAttribute("fruits", list);

        // トランザクション動作確認     
        if(after_name.equals("非検査例外")) {
            //  非検査例外の時にはロールバックが発生します。      
            System.out.println("非検査例外発生");
            throw new RuntimeException();
        }
        if(after_name.equals("検査例外")) {
            // 検査例外の時にはそのままコミットされます。          
            System.out.println("検査例外発生");
            throw new Exception();
        }
        return "index";
    }

    // 例外キャッチ
    @ControllerAdvice
    public class ExceptionHandlerAdvisor {
         @ExceptionHandler
         public String catchError(RuntimeException e){
            System.out.println("非検査例外キャッチ");
            return "error";
         }
         @ExceptionHandler
         public String catchError(Exception e){
            System.out.println("検査例外キャッチ");
            return "error";
         }
    }
  :
}

동작 확인



비검사 예외, 검사 예외 각각의 움직임을 확인해 봅시다.

비검사 예외일 때




mysql> select * from fruits;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | みかん    |
|  2 | ばなな    |
|  3 | りんご    |
+----+-----------+
3 rows in set (0.00 sec)

-- アップデート実行するが、非検査例外である RuntimeException がスローされる。

mysql> select * from fruits;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | みかん    |
|  2 | ばなな    |
|  3 | りんご    |
+----+-----------+
3 rows in set (0.01 sec)

みかん非検査例外로 업데이트 될 것이라고 생각하지만 트랜잭션 처리 중 예외 발생으로 인해 롤백되었습니다. 즉, 갱신 처리는 없었던 것으로 되어 있네요.

검사 예외일 때




mysql> select * from fruits;
+----+-----------+
| id | name      |
+----+-----------+
|  1 | みかん    |
|  2 | ばなな    |
|  3 | りんご    |
+----+-----------+
3 rows in set (0.00 sec)

-- アップデート実行するが、検査例外である Exception がスローされる。

mysql> select * from fruits;
+----+--------------+
| id | name         |
+----+--------------+
|  1 | 検査例外     |
|  2 | ばなな       |
|  3 | りんご       |
+----+--------------+
3 rows in set (0.00 sec)

비검사 예외 때와 같이 "귤"이 "검사 예외"로 갱신되지 않을 것을 기대하고 있었습니다만, 이번 throw 한 예외는 検査例外 때문에 커밋 되어 버렸습니다.

이런 움직임이 있다는 것을 알아 두지 않으면 위험하네요.

실제로 움직이고 싶은 분



자신의 SpringBoot 프로젝트 환경을 동료에게 전달합시다. 을 참고로, 이하의 리포지터리를 클론해 주시면 동작한다고 생각합니다.
# STSプロジェクトを入手します
git clone -b demo_transaction https://gitlab.com/msrx9/sample_springboot_crud.git

# MySQL環境を入手します
git clone https://gitlab.com/msrx9/sample_docker_mysql.git

도움을 준 기사


  • Spring Boot의 트랜잭션 처리 (MyBatis / MySQL)
  • 예외 발생시의 응답을 어플리케이션 공통으로 정형하자.
  • Spring에서 트랜잭션 관리
  • 좋은 웹페이지 즐겨찾기