现在的位置: 首页 > 综合 > 正文

SpringMVC+MyBatis配置声明式事务的问题

2019年09月05日 ⁄ 综合 ⁄ 共 2695字 ⁄ 字号 评论关闭

网络上关于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配置文件)

<!-- 自动扫描组件,这里不扫描 controller,它们是在ApplicationContext-mvc.xml中配置扫描的,如果不去除会影响事务管理   -->
<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配置文件)

<!-- 扫描所有的controller 但是不扫描service-->
<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/

抱歉!评论已关闭.