为了账号安全,请及时绑定邮箱和手机立即绑定

使用spring+springMVC组合开发,声明式事务失效

标签:
Spring

在整合springMVC+ibatis+spring框架时采用的是声明式事务,代码写完后故意测试了一下事务是否生效,写了一个测试方法:

public int[] delAndUpdate()  { 

        int a = testDao.delCart(); 

        int c = testDao.insertCart(); 

        int b = testDao.updateCart(); 

        int[] count = new int[] { a, c, b }; 

        return count; 

}

有增删改三种操作类型,最后一个update操作时候故意把sql写错,在执行时候就会抛出异常,再通过查看数据库看前两条数据是否删除和插入,杯具的是事务竟然没回滚,以为配置写的有问题

<!--声明式事务控制  --> 

    <bean id="transactionManager" class="org.springframework.jdbc.datasource.DataSourceTransactionManager"> 

        <property name="dataSource" ref="dataSource"/> 

    </bean> 



    <!-- 指定事务切入点 --> 

    <aop:config> 

        <aop:pointcut id="serviceOperation" expression="execution(* cn.myshop.service.*.*(..))" /> 

        <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice" /> 

    </aop:config> 



    <tx:advice id="txAdvice" transaction-manager="transactionManager"> 

        <tx:attributes> 

            <!-- 读取数据方法,一般采用只读事务--> 

            <tx:method name="get*" read-only="true"/> 

            <tx:method name="query*" read-only="true"/> 

            <tx:method name="find*" read-only="true"/> 

            <tx:method name="load*" read-only="true"/> 



            <!--以下方法,如save,update,insert等对数据库进行写入操作的方法,当产生Exception时进行回滚 --> 

            <tx:method name="insert*"  /> 

            <tx:method name="update*"  /> 

            <tx:method name="save*"  /> 

            <tx:method name="add*"  /> 

            <tx:method name="create*"  /> 

            <tx:method name="del*"  /> 

            <tx:method name="remove*"  /> 

            <tx:method name="batchCommit*"  /> 

                <!--2015-03-11,修改为抛出异常都进行回滚 --> 

            <tx:method name="*" rollback-for="Exception"/> 

        </tx:attributes> 

    </tx:advice>

经仔细查看和网上的配置对比,发现没什么问题,实在想不到什么地方有问题,之后google了半天,造成声明式事务无效不回滚的原因主要有几个(事务配置错了就不说了):

  • 1、由于数据库为mysql,网上有说法是

mysql默认存储引擎为MyISAM是不支持事务的,

需要设置为InnoDB模式,通过show engines; 命令看到

webp

InnoDB已经是默认的存储引擎,查看操作的表

webp

也为InnoDB模式,又看了my.ini中的配置

default-storage-engine=INNODB

都没问题,看来是其它地方的问题了。

2、另一种说法,不太相信,说是Spring的声明式事务需要抛出RuntimeException后才会触发事务的回滚,是这样吗,添加抛出RuntimeException依然没回滚,对于抛出RuntimeException事务才生效说法只能是一连串疑问了。

3、英语不杂地,官方文档也只能沉睡了,无奈继续google,最后在iteye上看到一帖子同为事务不生效

其中有一兄弟的回帖:

1.root-context.xml 

<!-- 不扫描带有@Controller注解的类。因为这些类已经随容器启动时,在servlet-context中扫描过一遍了 --> <context:component-scan base-package="com.kimho"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Controller"/> </context:component-scan> 2、servlet-context.xml: 

<!-- 扫描业务组件,让spring不扫描带有@Service注解的类(留在root-context.xml中扫描@Service注解的类),防止事务失效 --> <context:component-scan base-package="com.kimho"> <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>

同样我也使用的spring注解+springMVC注解,默认情况下spring应该先加载applicationContext.xml,之后再加载springMVC-servlet.xml,按那兄弟说法可能会造成事务失效。

我的springMVC-servlet.xml配置如下

<mvc:annotation-driven /> 

    <context:component-scan base-package="cn.myshop"/>

而applicationContext.xml没有再配置component-scan,本以为spring和springMVC同根生,使用同一个component-scan即可,没想到还相煎甚急,那就修改配置测试一下。

springMVC-servlet.xml修改为:

<mvc:annotation-driven /> <context:component-scan base-package="cn.myshop"> 

    <context:exclude-filter type="annotation" expression="org.springframework.stereotype.Service"/> </context:component-scan>

applicationContext.xml中添加

    <context:component-scan base-package="cn.myshop"/>

重启tomcat,测试事务正常回滚,还真是这个原因,另外也不需要抛出RuntimeException。



作者:一文艺书生
链接:https://www.jianshu.com/p/0af1f0f038cf


点击查看更多内容
TA 点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
  • 推荐
  • 评论
  • 收藏
  • 共同学习,写下你的评论
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消