3.1一個簡單的Java語言程式 這是程式雖然很簡單,但是所有的Java程式都具有這種結構,因此還是值得花一些時間來研究的。首先,Java區分大小寫。如果出現了大小寫拼寫錯誤(例如:將main拼寫成Main),程式將無法運行。 下麵逐行的查看這段源代碼。關鍵字pubilc稱為訪問修飾符(access ...
NEVER
不使用事務,如果當前事務存在,則拋出異常
驗證:
@Service public class PrService { @Autowired PrDao dao; @Transactional public void savea() { dao.a();//保存第一條數據 saveb(); } @Transactional(propagation = Propagation.NEVER) private void saveb() { dao.b();//保存第二條數據 int i=1/0; } }
寫一個controller調用這個savea方法,頁面看到的是/ by zero,資料庫中兩條數據都沒有插入進去,都回滾了。照說設置了Propagation.NEVER,應該saveb方法根本執行不了,報never的錯。為什麼執行了呢?
因為是直接調用的saveb(),不是從代理對象上調用的方法,改成這樣:
@Service public class PrService { @Autowired PrDao dao; @Autowired PrService prService; @Transactional public void savea() { dao.a();//保存第一條數據 prService.saveb(); } @Transactional(propagation = Propagation.NEVER) private void saveb() { dao.b();//保存第二條數據 int i=1/0; } }
註意這裡是 prService.saveb()和前面不同,但是居然在 dao.b(); 這一行報了一個空指針的錯誤,這就詭異了,這個dao明明在上面的savea方法裡面還有值的,你知道是為什麼嗎?
原來saveb方法的修飾符是private,導致代理對象無法繼承這個方法。改成public
public void saveb()
再次測試,看到期待的報錯了:
Existing transaction found for transaction marked with propagation 'never'
MANDATORY
當前存在事務,則加入當前事務,如果當前事務不存在,則拋出異常。
這裡把MANDATORY放在saveb方法上,就要把savea方法上的transactional註解去掉,才能看到報錯。
@Service public class PrService { @Autowired PrDao dao; @Autowired PrService prService; public void savea() { dao.a();//保存第一條數據 prService.saveb(); } @Transactional(propagation = Propagation.MANDATORY) public void saveb() { dao.b();//保存第二條數據 } }
或者直接把MANDATORY放在a方法上也會報錯:
@Service public class PrService { @Transactional(propagation = Propagation.MANDATORY) public void savea() { } }
報錯如下
No existing transaction found for transaction marked with propagation 'mandatory'
REQUIRES_NEW
創建一個新事務,如果存在當前事務,則掛起該事務。
可以理解為設置事務傳播類型為REQUIRES_NEW的方法,在執行時,不論當前是否存在事務,總是會新建一個事務。
現在寫一個demo驗證,savea方法調用saveb方法,希望saveb方法裡面異常了且事務回滾,savea方法裡面不回滾
下麵驗證:
同樣為了在避免事務失效,在代理對象上調用方法,將被調用的方法放到一個單獨的類中:
@Service public class PrService { @Autowired PrDao dao; @Autowired SaveBService saveBService; @Transactional public void savea() { dao.a();//插入第一條數據 saveBService.saveb(); } }
@Service public class SaveBService { @Autowired PrDao dao; @Transactional(propagation = Propagation.REQUIRES_NEW) public void saveb() { dao.b();//插入第二條數據 int i = 1/0; } }
這裡PrService的savea方法調用SaveBService的saveb方法,寫一個controller訪問savea方法,頁面看到一個異常 / by zero,再檢查資料庫,兩條數據都有沒有插入進去。這是為什麼呢?看上去第二個方法已經寫到獨立的類中了。
原來是因為saveb方法拋出的異常savea方法沒有捕獲,又拋出去了,當然要回滾了。寫個try catch就行:
@Transactional public void savea() { dao.a();//插入第一條數據 try { saveBService.saveb(); }catch (Exception e) { System.out.println("some error"); } }
再次測試,第二條數據沒有插入,第一條數據插入到資料庫了,頁面也看不到報錯了。