时间:2021-05-20
在开发中,遇到了sql语句报错,但是并没有回滚的情况。
经过几天的排查,终于找到了事务没有回滚的原因。
原来的项目用的是informix的数据库,原来针对事务回滚的机制都是好用的。我本地用的是mysql数据库。
先将程序代码与spring-mybatis.xml配置文件拿过来:
1、程序代码:
这个问题是在验证增删改查返回值时发现的。
两个操作,删除时,因为关联了外键,所以会报错,此时正常情况更新的语句也会回滚,但是并没有。
/** *@Author: Administrator on 2020/3/12 15:15 *@param: *@return: *@Description:查询同步情况 */ @Override public PageInfo getSyncstatusPages(Syncstatus vo, int pageNo, int pageSize) { PageHelper.startPage(pageNo, pageSize); //2-3删除失败:例如有外键:报异常 //3更新:返回值自己定义,可以是void,int //3-1更新成功:没有数据,返回值为0 //int update_no = yylfHttpServletMapper.update_no("0"); //3-2更新成功:有多条数据,返回更新的数据条数 int update_duotiao = yylfHttpServletMapper.update_duotiao_systemcode("2"); int delete_fail = yylfHttpServletMapper.delete("1"); //3-3更新失败:例如有外键,报异常 //int update_fail = yylfHttpServletMapper.update_fail("1"); //4查询 //4-1 没数:String 类型返回null //Object object = yylfHttpServletMapper.select("0"); //4-1 没数:集合 类型返回[]空集合 //Syncstatus syncstatus3 = new Syncstatus(); //syncstatus3.setStatus("7"); //List<Syncstatus> page0 = yylfHttpServletMapper.getSyncstatusList(syncstatus3); //4-1 没数:int 类型返回null,如果定义为int会报错。因为没数时返回null,可以将返回类型改为String //String i = yylfHttpServletMapper.select_int(0); //4-1:当返回值为对象时,若返回值为空,则返回null //4-2 有数 List<Syncstatus> pages = yylfHttpServletMapper.getSyncstatusList(vo); return new PageInfo<Syncstatus>(pages); }2、对数据库的操作:
<update id="update_duotiao_systemcode"> UPDATE aaa SET systemcode = '3' WHERE systemcode = #{systemcode,jdbcType=VARCHAR} </update><delete id="delete"> delete from aaa where uuid = #{uuid,jdbcType=VARCHAR} </delete>3、配置文件:
<?xml version="1.0" encoding="UTF-8"?><beans xmlns="http://PAN foreign key (uuid)references aaa (uuid);insert into bbb (uuid,systemcode,status)value ('1','2','2');-- 验证事支持DELETE from aaa where uuid != '1';insert into aaa (uuid,systemcode,status)value ('2','2','2');SELECT * FROM aaa;排查过程共查找了下述方面:
1、排除数据库原因:
查看mysql数据库是支持事务的;而且用informix数据库进行了验证,同样没有回滚。
2、验证了impl的类型等均为问题。
3、查看了事务的配置信息也正确好用。
4、验证了系统其它的一些方法,发现是支持事务的。
5、将这两个语句放到其它方法里也好用。
6、事务是在service层处理的,在控制层也加了异常捕获(这个操作并不会影响事务回滚,即使不catch,也会回滚的)
最终锁定问题原因:是因为方法名称的问题。
当将方法名改成其它的,不以get开头,不报错。
这个问题很坑,因为本以为为配置文件中的get*,会使这个方法的事务起作用,谁知道恰恰get*的这个配置虽然起作用了,但是结果却是事务不回滚,在将该配置改为
<tx:method name="get*" propagation="SUPPORTS" rollback-for="java.lang.Exception"/>
也没有用,最后将其注释掉,事务回滚。走了下面的配置:
<tx:method name="*" propagation="REQUIRED" rollback-for="java.lang.Exception" />
需要注意的是tx:method 的name属性指的是方法名。
将SUPPORTS改为REQUIRED后,事务也进行回滚。最终得到原因:是因为propagation的配置信息不正确。
拓展:
一、在声明式的事务处理中,要配置一个切面,其中就用到了propagation,表示打算对这些方法怎么使用事务,是用还是不用,其中propagation有七种配置,REQUIRED、SUPPORTS、MANDATORY、REQUIRES_NEW、NOT_SUPPORTED、NEVER、NESTED。默认是REQUIRED。
二、Spring中七种Propagation类的事务属性详解:
三、注意.
这个配置将影响数据存储,必须根据情况选择。
问题往往出现在你忽略的地方。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。
声明:本页内容来源网络,仅供用户参考;我单位不保证亦不表示资料全面及准确无误,也不保证亦不表示这些资料为最新信息,如因任何原因,本网内容或者用户因倚赖本网内容造成任何损失或损害,我单位将不会负任何法律责任。如涉及版权问题,请提交至online#300.cn邮箱联系删除。
Spring多配置文件有什么好处?按照目的、功能去拆分配置文件,可以提高配置文件的可读性与维护性,如将配置事务管理、数据源等少改动的配置与配置bean单独分开。
一般我们在Spring的配置文件application.xml中对Service层代码配置事务管理,可以对Service的方法进行AOP增强或事务处理如事务回滚
前沿:通过对spring事务管理有了比较深入学习,本文将不做实例,而是指定具体的类和配置文件进行讲解。本文内容: 1、了解什么是声明式事务? 2、声明式事务
配置事务:使用的tx前缀的标签,导入tx的命名空间配置事务管理器,把事务管理器交给Spring管理:事务的策略transaction-manager:事务增强基
Spring事务管理Spring支持两种方式的事务管理:编程式事务管理:通过TransactionTemplate手动管理事务,实际应用中很少使用,使用XML配