1. 程式人生 > 其它 >Spring的event的自帶執行緒池,在執行過程中,發生異常事務會回滾嗎

Spring的event的自帶執行緒池,在執行過程中,發生異常事務會回滾嗎

技術標籤:Spring執行緒池事務回滾執行緒池與事務Spring

背景

  1. 推薦閱讀Spring的event的基本使用過程與理解
  2. 測試當執行緒池中的任務發生異常(RuntimeException)不捕獲與@Transactional關係

過程

  • 測試事務(入口處沒有註解@Transactional)
  1. 測試邏輯。業務邏輯程式碼先執行了資料庫的更新操作,後續邏輯發生空指標異常。
  2. 資料庫情況
    在這裡插入圖片描述
  3. 程式碼情況
    監聽程式碼情況
	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent)
{ System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件"); // 具體的業務邏輯過程 this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator()); }

具體業務邏輯程式碼。
studentService.selectByName()和studentService.update()都添加了@Transactional註解。異常是RuntimeException,因此Spring是能夠感知到的。

	@Override
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.
println("myEvent.operator: " + operator); Student sara = studentService.selectByName("sara"); sara.setName("Ted"); studentService.update(sara); String str = null; System.out.println(str.equals("null")); }
  1. 測試結果(未回滾,資料被修改 了)
    在這裡插入圖片描述
  • 測試事務(入口處有註解@Transactional),其他為原來初始情況。
    監聽程式碼
	@EventListener
    @Async("AsyncTaskExecutor")
    @Transactional
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");

        // 具體的業務邏輯過程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }

測試結果(回滾了,沒有修改成功)
在這裡插入圖片描述

  • 測試事務(入口處沒有註解@Transactional,業務邏輯入口處有@Transactional ),其他為原來初始情況。
 	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");

        // 具體的業務邏輯過程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }
 	@Override
    @Transactional
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.println("myEvent.operator: " + operator);
        Student sara = studentService.selectByName("sara");
        System.out.println(sara.getName());
        sara.setName("Ted");
        studentService.update(sara);
        String str = null;
        System.out.println(str.equals("null"));

    }

測試結果(事務回滾)
在這裡插入圖片描述

  • 測試事務(入口處有註解@Transactional,業務邏輯入口處有@Transactional ,studentService.update(sara)@Transactional去掉)。
 	@EventListener
    @Async("AsyncTaskExecutor")
    public void handleMyEvent(MyEvent myEvent) {
        System.out.println("執行緒:" + Thread.currentThread().getName() + "執行了MyEvent事件");

        // 具體的業務邏輯過程
        this.eventService.handleEvent(myEvent.getAddr(), myEvent.getTime(), myEvent.getOperator());
    }
 	@Override
    @Transactional
    public void handleEvent(String addr, Date time, String operator) {
        System.out.println("event: 模擬具體的業務邏輯處理過程, 這裡單純地打印出來即可");
        System.out.println("myEvent.addr: " + addr);
        System.out.println("myEvent.time: " + time);
        System.out.println("myEvent.operator: " + operator);
        Student sara = studentService.selectByName("sara");
        System.out.println(sara.getName());
        sara.setName("Ted");
        // 此方法沒有@Transactional
        studentService.update(sara);
        String str = null;
        System.out.println(str.equals("null"));

    }

測試結果(事務回滾)
在這裡插入圖片描述

小結

  • Spring的執行緒池用在Event中,如果執行緒池中的執行緒在處理業務邏輯的過程中,發生了RuntimeExcepion時,與Spring註解@Transactional用在的哪個層級,然後導致事務會回滾,有非常大的關係。這個demo實驗有很好的參考價值
  • 注意@Transactional預設回滾的異常級別是RuntimeExcepion,而不是Excption
  • @Transactional。Spring預設的傳播行為REQUIRED,業務方法需要在一個事務中執行,如果方法執行時,已處在一個事務中,那麼就加入該事務,否則自己建立一個新的事務。