SSM中實現在Controller中新增事務管理
本人使用:
- 整合開發環境:idea
- 專案管理工具:maven
- 資料庫:oracle
- 框架:Spring+SpringMVC+myBatis
一般而言,事務都是加在Service層的,但也可以加在Controller層。。
看了不少人的部落格,總結出兩個方法:
- 在controller層寫程式設計式事務
- 將事務配置定義在Spring MVC的應用上下文(spring-mvc.xml)中
現在具體來說說怎麼實現的:
1.在controller層寫程式設計式事務【繁瑣,不推薦】:
1.spring-mybatis.xml中事物管理器的配置依舊
<!-- 配置資料來源事務 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="dataSource"/> </bean> <!-- 註解方式配置事務 @Transactional 但因為是在controller中寫程式設計式事務,這裡可以不配置<tx:annotation-driven transaction-manager="transactionManager" /> --> <tx:annotation-driven transaction-manager="transactionManager" />
2.在controller中的方法裡編寫事務
//在每個controller中注入transactionManager @Resource private PlatformTransactionManager transactionManager; @PostMapping(value = "setCode") @ResponseBody public void setCode(Invoice invoice, InvoiceAddress invoiceAddress,String token,String orderIDs, Integer pid,HttpServletResponse response){ DefaultTransactionDefinition defaultTransactionDefinition = new DefaultTransactionDefinition(); defaultTransactionDefinition.setPropagationBehavior(TransactionDefinition.PROPAGATION_REQUIRED); TransactionStatus status = transactionManager.getTransaction(defaultTransactionDefinition); try { invoiceService.insert(token,pid,invoice); int iID= invoice.getId(); String substring = orderIDs.substring(0, orderIDs.length()-1); String[] split = substring.split(","); for (String string2 : split) { bOrderService.updateIStatus("1",string2); } invoiceOrderService.insert(iID,substring); if(Integer.parseInt(invoice.getiType())==1){ invoiceAddressService.insert(iID,invoiceAddress); } System.out.println("======製造一個執行時異常aa======"); System.out.println("執行時異常:"+100/0); //沒有異常便手動提交事務 transactionManager.commit(status); printJson(response,result(200,"ok")); }catch (Exception e){ //有異常便回滾事務 transactionManager.rollback(status); e.printStackTrace(); printJson(response,result(500,"false")); } }
2.將事務配置定義在Spring MVC的應用上下文(spring-mvc.xml)中【簡單明瞭、一勞永逸】
1,spring-mybatis.xml中事物管理器配置不變
2,在spring-mvc.xml中也定義事務配置:
<!-- 名稱空間中 加入: xmlns:tx="http://www.springframework.org/schema/tx" http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd --> <tx:annotation-driven/>
3,將 @Transactional(rollbackFor = { Exception.class })註解打在Controller上
@Controller
@RequestMapping(value = "/invoiceC")
@Transactional(rollbackFor = { Exception.class })
public class InvoiceController extends BaseController {
@Autowired
private InvoiceService invoiceService;
@Autowired
private InvoiceOrderService invoiceOrderService;
@Autowired
private InvoiceAddressService invoiceAddressService;
@Autowired
private BalanceRechangeOrderService bOrderService;
@PostMapping(value = "setCode")
@ResponseBody
public void setCode(Invoice invoice, InvoiceAddress invoiceAddress,String token,String orderIDs,
Integer pid,HttpServletResponse response){
invoiceService.insert(token,pid,invoice);
int iID= invoice.getId();
String substring = orderIDs.substring(0, orderIDs.length()-1);//擷取最後一個
String[] split = substring.split(",");//以逗號分割
for (String string2 : split) {
bOrderService.updateIStatus("1",string2);
}
invoiceOrderService.insert(iID,substring);
if(Integer.parseInt(invoice.getiType())==1){
//紙質發票,收貨地址
invoiceAddressService.insert(iID,invoiceAddress);
}
System.out.println("======製造一個執行時異常aa======");
System.out.println("執行時異常:"+100/0);
printJson(response,result(200,"ok"));
}
}
現在,我們來談談為什麼之前??==》
- 在spring-mybatis.xml的<aop:config>新增對Controller的宣告式事務攔截
- 在Controller的class加上@Transactional
兩者均未生效呢???
原理:因為spring容器和spring-mvc是父子容器。在伺服器啟動時,會先載入web.xml配置檔案 ==> 再載入spring配置檔案 ==> 再回到web.xml【載入監聽器;載入過濾器;載入前端控制器】==>再載入springMVC配置檔案
在Spring配置檔案中,我們掃描註冊的是service實現類,就算掃描註冊了controller 也會在後面載入SpringMVC配置檔案[掃描註冊controller]覆蓋掉,所以想要在controller中實現事務管理,僅在spring配置檔案配置<tx:annotation-driven>或<aop:config>是沒有效果的,必須將事務配置定義在Spring MVC的應用上下文(spring-mvc.xml)中。
因為在spring-framework-reference.pdf文件中說明了: <tx:annoation-driven/>只會查詢和它在相同的應用上下檔案中定義的bean上面的@Transactional註解