Spring Mybatis @Transactional注解事务不生效

最近突然发现用Spring和MyBatis搭建的一个项目,Service报错了,数据仍然可以写入数据库,项目使用的是@Transactional注解声明式事务。配置方式如下:

1
2
3
4
5
6
<!--transaction config -->
<bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
<property name="dataSource" ref="dataSource"/>
</bean>
<!-- 扫描@Transactional注解的类定义事务 -->
<tx:annotation-driven mode="proxy" transaction-manager="transactionManager" proxy-target-class="true"/>

在Service上使用@Transactional(readonly = true)注解声明这个Service为只读,但是发现方法上没有加@Transactional注解数据可以写入数据库,而且即使报错,数据也可以进库。在确定事务相关的配置,以及数据源、MyBatis相关的配置没有问题之后,依旧没有解决,很是崩溃。

最后发现,是扫描包冲突了,Spring扫描完Service以后,MVC又扫了一遍。其实这个问题在之前做异步执行的时候,就发现在Service的方法上添加注解@Async不生效,一直是单线程的,各种尝试之后用其他方式暂时解决了,没想到这次还是没逃过这个问题。

解决方式为:在context.xml里排除扫描Controller类,在mvc里排除Service只扫描Controller,如下:

spring-context.xml

1
2
3
4
5
<context:annotation-config/>
<context:component-scan base-package="win.wellcoding.service">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Service"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
</context:component-scan>

spring-mvc.xml

1
2
3
4
5
6
<context:annotation-config/>
<context:component-scan base-package="win.wellcoding.controller">
<context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
<context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
</context:component-scan>
<mvc:annotation-driven validator="validator" conversion-service="conversionService"/>