网络上关于Spring声明式事务的博客一堆一堆地,原本不用自己再记笔记,但我最近在用SpringMVC+MyBatis时遇到了事务问题;深知自己水平不高,忘东西又快,因此一解决问题还是第一时间记下来,以备后用。
我的环境是Spring、SpringMVC、MyBatis3、MariaDB和Tomcat
我遇到的问题是事务不起作用,虽然多次数据库操作中有异常出现,但还是部分提交,并没有回滚;
我的配置是这样的:
- <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
- <property name="dataSource" ref="dataSource" />
- </bean>
-
- <tx:advice id="txAdvice" transaction-manager="transactionManager">
- <tx:attributes>
- <tx:method name="delete*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception"/>
- <tx:method name="insert*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
- <tx:method name="update*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
- <tx:method name="save*" propagation="REQUIRED" read-only="false" rollback-for="java.lang.Exception" />
- <tx:method name="*" propagation="REQUIRED" read-only="true"/>
- </tx:attributes>
- </tx:advice>
- <aop:config>
- <aop:pointcut id="pc" expression="execution(* com.xss.*.*.service.impl.*.*(..))" />
- <aop:advisor pointcut-ref="pc" advice-ref="txAdvice" />
- </aop:config>
这段配置应该是没有问题的,于是我就想会不会是MariaDB的存储引擎不支持事务,于是从网上找到了这么一段话:
MariaDB默认的存储引擎是Maria,不是MyISAM。Maria可以支持事务,但是默认情况下没有打开事务支持,因为事务支持对性能会有影响。 可以通过以下语句,转换为支持事务的Maria引擎:
ALTER TABLE ‘tablename’ ENGINE=MARIA TRANSACTIONAL=1;
但我按照上面所述修改了数据库的存储引擎,事务仍然不起作用。
注:在MariaDB(MySQL)数据中,InnoDB和BerkeleyDB两种存储引擎是支持事务的,MariaDB引进的新引擎Aria默认不支持事务,可以通过上面的代码修改。
纠结了许久终于发现还是自己的配置出了问题,但并非是事务配置有问题,而是Spring组件扫描配置出了问题。
由于采用的是SpringMVC、 MyBatis,故统一采用了@Service、@Controller注解来声明Service和Controller 组件,于是我在Spring和SpringMVC的配置文件均用一行代码配置了Spring的组件自动扫描:
- <context:component-scan base-package="com.xss.crm" />
而由于服务器启动时的加载Spring相关配置文件的顺序为applicationContext.xml(Spring的配置文件) ---> applicationContext-mvc.xml(SpringMVC的配置文件),按照上面的配置Spring加载applicationContext.xml配置文件时会加载@Controller注解标注的Controller组件,并且对其进行扫描装配,但是此时的Service还没有进行事务增强处理,得到的将是原样的Service(没有经过事务加强处理,故而没有事务处理能力),所以我们应用在applicationContext.xml(Spring配置文件)中不扫描Controller,而在applicationContext-mvc.xml(SpringMVC配置文件)中不扫描Service。
于是Spring和SpringMVC配置应该像下面的这样:
applicationContext.xml(Spring配置文件)
-
- <context:component-scan base-package="com.xss.crm">
- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
- </context:component-scan>
applicationContext-mvc.xml(SpringMVC配置文件)
-
- <context:component-scan base-package="com.xss.crm">
- <context:include-filter type="annotation" expression="org.springframework.stereotype.Controller"/>
- <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/>
- </context:component-scan>
修改配置后再测试,事务成功回滚。
参考博客:http://sence-qi.iteye.com/blog/1328902/