網頁

2020/11/14

Spring Boot @Trancsational 捕捉例外不會觸發回滾 try-catch exception won't trigger rollback

之前撰寫@Transactional 方法間呼叫的回滾範圍時,弄錯了try catch捕捉例外時@Trancsational的rollback效果。

範例環境:

  • Spring Boot 2.3.2.RELEASE
  • Spring Data JPA

掛有@Trancsational的方法若執行時發生例外被try catch捕捉且不再拋出例外,則該方法的交易不會rollback。

例如下面DemoService有兩個方法皆為新增資料並故意拋出錯誤,差別在於是否有使用try catch捕捉例外錯誤。無捕捉錯誤的方法的交易才會回滾,而有捕捉錯誤的方法則否。

DemoService

@Service
public class DemoService {

    @Autowired
    private EmployeeRepository employeeRepository;

    /** 無try-catch 會觸發@Transactional rollback */
    @Transactional
    public void addWithoutTryCatch() {
        employeeRepository.save(new Employee("John"));
        throw new RuntimeException("Save data error!");
    }

    /** 有try-catch 不會觸發@Transactional rollback*/
    @Transactional
    public void addWithTryCatch() {

        try {
            employeeRepository.save(new Employee("John"));
            throw new RuntimeException("Save data error!"); // 錯誤被try catch捕捉了
        } catch (Exception e) {
        }

    }

}

測試。

DemoServiceTests

@SpringBootTest
public class DemoServiceTests {

    @Autowired
    DemoService demoService;

    @Autowired
    EmployeeRepository employeeRepository;

    @Test
    void addWithoutTryCatch_rollback() {

        try {
            demoService.addWithoutTryCatch();
        } catch (Exception e) {
        }

        List<Employee> employeeList = employeeRepository.findAll();
        Assertions.assertEquals(0, employeeList.size()); // 有rollback資料未新增
    }

    @Test
    void addWithTryCatch_noRollback() {

        demoService.addWithTryCatch();
        List<Employee> employeeList = employeeRepository.findAll();
        Assertions.assertEquals(1, employeeList.size()); // 無rollback資料有新增

    }
}


參考github


沒有留言:

張貼留言