因爲 項目開發,有第三方的回調。。。可能須要用到 多線程,因此 測試了一下 spring的多線程事務。html
new Thread(new Runnable() { @Override public void run() { System.out.println("22>>"); boscRequestLogService.test(); } }).start(); 通過測試, 若是 在 boscRequestLogService.test() 方法裏面 ,產生了異常,是能夠回滾的。 也就是說, 新線程,在 boscRequestLogService.test() 方法裏面的 全部調的方法 都是 對應 spring 聲明事務都是能夠起做用的,和 controller 沒有關係。
public void test() { System.out.println("33>>"); BoscRequestLog log = this.getByRequestNo("20171221100422"); log.setReturnErrorMsg("test8888"); this.update(log); System.out.println("44>>"); int a = 1; if (a == 2) { System.out.println("55>>"); throw new NullPointerException("我是空"); } test2(); } public void test2() { new Thread(new Runnable() { @Override public void run() { // 自定義事務控制,達到 以後的業務出現了異常這個充值裏面的記錄不會回滾 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); def.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRES_NEW); // 事物隔離級別,開啓新事務,這樣會比較安全些。 TransactionStatus status = transactionManager.getTransaction(def); // 得到事務狀態 try { System.out.println("66>>"); BoscRequestLog log = getByRequestNo("20171221100646"); log.setReturnErrorMsg("000"); update(log); int a = 1; if (a == 1) { System.out.println("77>>"); throw new NullPointerException("我是空"); } transactionManager.commit(status); // 提交事務 } catch (Exception e) { // TODO Auto-generated catch block // e.printStackTrace(); System.out.println("...回滾"); transactionManager.rollback(status); // 回滾事務 throw new NullPointerException("我是空"); } } }).start(); }
對應 在 service 層裏面 創建 多線程執行 方法,那麼 聲明事務就不會起做用了,出現異常不會回滾的。 因此就須要再 多線程裏面 本身控制事務了 因此使用了 DefaultTransactionDefinition def = new DefaultTransactionDefinition(); 。。。spring
這樣在 多線程裏面 產生了異常, 多線程裏面的方法是能夠回滾事務的安全
不過有一個特殊狀況就是 。 好比 上面 test2 方法產生了 異常,拋出去了,在 test 方法 並不能 回滾事務。 也就是 多線程來講, 對於 以前 執行的方法,是不能回滾事務的。聲明事務沒有做用。 除非 test 方法 本身 定義一個事務控制, try-catch test2 方法,有異常就 回滾就能夠。多線程
// spring沒法處理thread的事務,聲明式事務無效ide