一、問題說明
項目框架采用SSM,集成了事務回滾(方式見下),在單元測試的時候,測試事務是有效的,但是在實際項目上線的時候,卻沒有效果。
二、集成方式
application-mybatis.xml(以下xml屏蔽了一些無關的細節)
<!-- 數據連接池 --> <bean id="datasource" class="com.alibaba.druid.pool.DruidDataSource"> <property name="driverClassName" value="${jdbc.driver.dev}"></property> <property name="url" value="${jdbc.url.dev}"></property> <property name="username" value="${jdbc.user}"></property> <property name="password" value="${jdbc.password}"></property> </bean> <!-- 事務管理器 --> <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> <property name="dataSource" ref="datasource"></property> </bean> <!-- 事務配置1:需手動注解 --> <!-- proxy-traget-class true對類進行代理,如果是false表示對接口進行代理,使用時需要在類或者方法上加上 @Transactional 注解。 --> <tx:annotation-driven transaction-manager="transactionManager" proxy-target-class="true" />
application-common.xml (關鍵是讓Spring管理排除Controller部分)
<!-- 會自動掃描com.mc.bsframe下的所有包,包括子包下除了@Controller的類。 --> <scpan:component-scan base-package="com.mc.bsframe"> <scpan:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <scpan:exclude-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </scpan:component-scan>
spring-mvc.xml (關鍵是只處理Controller部分)
<!-- 只掃描base-package下的用Controller注解的類。 --> <context:component-scan base-package="com.mc.bsframe.controller"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <!-- 必須要包括ControllerAdvice才能處理全局異常。 --> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> </context:component-scan>
基本關於事務的配置如上,但是我發現,偶爾會有失效的情況,
三、分析
為什么Junit4測試下有效,猜測因為Junit4下創建的是一個上下文對象,而實際項目是一個Spring上下文,一個SpringMVC上下文?
四、解決方法
在spring-mvc.xml中添加排除掃描Service的配置,以前語句僅僅是包含了Controller和ControllerAdvice,如下:
<!-- 只掃描base-package下的用Controller注解的類。 --> <context:component-scan base-package="com.mc.bsframe.controller"> <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" /> <!-- 必須要包括ControllerAdvice才能處理全局異常。 --> <context:include-filter type="annotation" expression="org.springframework.web.bind.annotation.ControllerAdvice" /> <!-- !!!最好加上這句讓SpringMVC管理的時候排除Service層,避免事務失效的問題。 --> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" /> </context:component-scan>