1 問題描述
在最近的一個專案中,採用springMVC、mybatis,發現一個很惱人的問題:事務管理不起作用!!網上查閱了大量的資料,嘗試了各種解決辦法,亦未能解決問題!
applicationContext.xml配置:
<context:annotation-config />
<!-- 引入jdbc屬性配置檔案 -->
<context:property-placeholder location="classpath:jdbc.properties" />
<!-- 資料來源 -->
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource">
<property name="driverClassName" value="${jdbc.driverClassName}"></property>
<property name="url" value="${jdbc.url}"></property>
<property name="username" value="${jdbc.username}"></property>
<property name="password" value="${jdbc.password}"></property>
</bean>
<bean id="ftpConfig" class="com.wtas.utils.CustomizedPropertyConfig">
<property name="location" value="classpath:ftp.properties" />
</bean>
<!-- 配置mybatis用到的sqlSessionFactory -->
<bean id="sqlSessionFactory" class="org.mybatis.spring.SqlSessionFactoryBean">
<property name="configLocation" value="classpath:mybatisConfig.xml" />
<property name="dataSource" ref="dataSource" />
<property name="typeAliasesPackage" value="com.wtas.study.domain,com.wtas.studygroup.domain,com.wtas.sys.domain,com.wtas.test.domain" />
<property name="mapperLocations" value="classpath*:com/wtas/**/*Mapper.xml" />
</bean>
<!-- 根據對映檔案動態生成dao的實現 -->
<bean class="org.mybatis.spring.mapper.MapperScannerConfigurer">
<property name="basePackage" value="com.wtas" />
<property name="annotationClass" value="org.springframework.stereotype.Repository" />
</bean>
<!-- 事務控制 -->
<bean name="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"></property>
</bean>
<tx:advice id="userTxAdvice" transaction-manager="transactionManager">
<tx:attributes>
<tx:method name="remove*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />
<tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" no-rollback-for="java.lang.RuntimeException" />
<tx:method name="add*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
<tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
<tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.RuntimeException" />
<tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="publish*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
<tx:method name="get*" propagation="SUPPORTS" read-only="true" />
<tx:method name="list*" propagation="SUPPORTS" read-only="true" />
<tx:method name="query*" propagation="SUPPORTS" read-only="true" />
<tx:method name="find*" propagation="SUPPORTS" read-only="true" />
<tx:method name="page*" propagation="SUPPORTS" read-only="true" />
</tx:attributes>
</tx:advice>
<tx:annotation-driven transaction-manager="transactionManager"/>
<!-- execution(public * com.wtas.*.service.*.*(..)) OR execution(public * com.wtas.*.*.*.service.*.*(..))-->
<aop:config>
<aop:pointcut id="pc" expression="execution(public * com.wtas.*.service.*.*(..))" />
<aop:advisor pointcut-ref="pc" advice-ref="userTxAdvice" />
</aop:config>
複製程式碼
springMVC.xml配置:
<!-- 這裡註冊轉換器 -->
<mvc:annotation-driven conversion-service="conversionService" />
<context:component-scan base-package="com.wtas"></context:component-scan>
<mvc:default-servlet-handler />
<!-- 註冊ConversionService -->
<bean id="conversionService" class="org.springframework.format.support.FormattingConversionServiceFactoryBean">
<!-- 轉換器 -->
<property name="converters">
<list>
<bean class="com.wtas.converter.StringToDateConverter">
<constructor-arg value="yyyy-MM-dd" />
</bean>
</list>
</property>
</bean>
<bean class="org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter">
<property name="messageConverters">
<list>
<bean class="org.springframework.http.converter.BufferedImageHttpMessageConverter" />
<bean class="org.springframework.http.converter.ByteArrayHttpMessageConverter" />
<bean class="org.springframework.http.converter.StringHttpMessageConverter" />
<bean class="org.springframework.http.converter.json.MappingJacksonHttpMessageConverter" />
</list>
</property>
</bean>
<!-- 檢視解釋類 -->
<bean id="viewResolver" class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/WEB-INF/jsps/" />
<property name="suffix" value=".jsp" />
<property name="viewClass" value="org.springframework.web.servlet.view.JstlView" />
</bean>
複製程式碼
2 排查過程
具體原理,請參考:深入分析Spring與Spring MVC容器。
3 解決問題
applicationContext.xml中新增:
<context:component-scan base-package="com.wtas">
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller" />
</context:component-scan>
複製程式碼
springMVC.xml中修改:
<!-- 掃描所有的controller 但是不掃描service-->
<context:component-scan base-package="com.wtas">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller" />
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service" />
</context:component-scan>
複製程式碼
4 總結問題
具體總結,可參見my.oschina.net/xianggao/bl…。