1. 程式人生 > >SSM中實現在Controller中新增事務管理

SSM中實現在Controller中新增事務管理

本人使用:

  • 整合開發環境:idea
  • 專案管理工具:maven
  • 資料庫:oracle
  • 框架:Spring+SpringMVC+myBatis

一般而言,事務都是加在Service層的,但也可以加在Controller層。。     

看了不少人的部落格,總結出兩個方法:

  1. 在controller層寫程式設計式事務
  2. 將事務配置定義在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"));

    }
}

現在,我們來談談為什麼之前??==》

  1. 在spring-mybatis.xml的<aop:config>新增對Controller的宣告式事務攔截
  2. 在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註解