SSM中,事務控制不生效問題
阿新 • • 發佈:2019-02-05
今天在使用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等其他方法上的事務,是忽略的