1. 程式人生 > >SSM中,事務控制不生效問題

SSM中,事務控制不生效問題

今天在使用ssm事務時,發現方法報錯,事務沒有回滾,弄了半天,終於解決,下面記錄一下
事務有兩種處理方式:
1、程式設計式事務,即使用配置檔案
2、宣告式事務,即使用註解
我這裡用的宣告式事務

1、spring的配置檔案

applicationContext.xml,上下文元件掃描應該排除掃描Controller

<context:component-scan base-package="cn.tisson.mos.*.*">
    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"
/> <context:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>

2、springmvc的配置檔案

springmvc.xml,上下文掃描應該只掃描controller

<context:component-scan base-package="cn.tisson.mos.*.controller">
        <context
:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice"/> </context:component-scan>

3、spring-myabatis的配置檔案

spring-mybatis.xml

中配置事務,並把該檔案插入到applicationContext.xml

<!-- (事務管理)transaction manager, use JtaTransactionManager for global tx -->
<bean id="transactionManager"  class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
   <property name="dataSource" ref="dataSource" />
</bean>
<!-- 宣告式事務 -->
<tx:annotation-driven transaction-manager="transactionManager"
                      proxy-target-class="true" />

問題

  • 為什麼要分開配置spring 和 mvc的掃描?
因為spring的context是父子容器,ContextLoaderListener監聽器載入spring配置檔案,
產生的是父容器,mvc載入mvc的配置檔案,產生了子容器,子容器對@Controller進行裝配掃描時,
也裝配了@Service註解的例項,因為在@Contoller例項依賴@Service例項,而@Service註解的例項,
也就是一般的事務控制層,應該是有父容器初始化,以保證事務的增強處理,否則會事務事務處理能力。

因此也就有了上面的兩個掃描,這是最關鍵的問題所在

  • 要確保資料庫支援事務

我試了好久,發現debug日誌都已經顯示事務回滾成功了,但資料庫還是沒有回滾,後面發現,原來是mysql資料庫的引擎沒有修改

在mysql資料庫中,通過show engines 可以檢視支援的引擎,其中只有InnoDBz才支援事務功能
修改mysql的預設引擎:
1) 在配置檔案中修改,針對整個mysql生效:
在[mysqld]下加入: default-storage-engine=INNODB
2)只修改某個表的:
在命令介面輸入 ALTER TABLE xxx TYPE = INNODB

注意點

  • @Transactional(readOnly = true) ,只能讀,預設是readOnly = false

  • 在類上加@Transactional(readOnly = true)是全域性,該類所有的public方法都有事務了,如果在方法上再加@Transactional,就是覆蓋了類的事務了

  • 事務配置中<tx:annotation-driven transaction-manager="transactionManager"
    proxy-target-class="true" />

    中的proxy-target-class="true"表示支援CGLB代理,如果不加,只支援JDK的代理,預設只支援面向介面,也就是說放在實現類上,事務不生效

  • @Transactional, 應該被放在public方法上,因為spring對private,protected等其他方法上的事務,是忽略的