在前天的《事务管理入门》一文发布之后,有读者联系说根据文章尝试,加了@Transactional注解之后,事务并没有回滚。...问题原因 在前文的描述中,我漏了一个细节,其实在示例代码中,与之前拿的基础例子在配置中有一个关键属性没有提到,就是下面这个配置: spring.jpa.database-platform=org.hibernate.dialect.MySQL5InnoDBDialect...这里特地采用了MySQL5InnoDBDialect,主要为了保障在使用Spring Data JPA时候,Hibernate自动创建表的时候使用InnoDB存储引擎,不然就会以默认存储引擎MyISAM...来建表,而MyISAM存储引擎是没有事务的。...所以,如果你的事务没有生效,那么可以看看创建的表,是不是使用了MyISAM存储引擎,如果是的话,那就是这个原因了! 除此之外,对于事务没有生效的可能还很多,比如,在同一个类中定义又调用等。
MySQL 事务小伙伴们都懂,通过 begin 开启事务,通过 commit 提交事务或者通过 rollback 回滚事务。...这就意味着带有 DDL 语句的事务将来没有办法 rollback。 我举一个简单的例子,大家一起来看下: 我们来一起看下我这里的测试逻辑: 首先查询总记录数有四条。 开启一个事务。...回滚。 再次查询数据。 到第六步的时候,我们发现查询到的数据只剩三条了,说明第五步的回滚并没有生效。原因就在于执行 alter 之前,事务已经被隐式提交了。...对于上面的案例,如果大家去掉第四步的 alter,那么回滚是可以回滚成功的,这个小伙伴们自己来测试,我就不演示了。...我举个简单例子: 可以看到,跟第一小节的测试步骤一样,只不过第四步换成一个 GRANT 语句,那么最终的事务回滚也会失效,原因就在于事务已经提交了。
之前做项目用到了事务回滚这个机制。...我把代码贴出来多多交流给点意见,我用的是laravel 5.1bane版本的, public static function createDeal($to_status, $params, $new_balance...create manage error"); } } \DB::commit(); } catch (\Exception $e) { //异常处理进行回滚...insert($trouble_params); } finally { self::createLog($params, $to_status); } } 以上这篇在laravel...中实现事务回滚的方法就是小编分享给大家的全部内容了,希望能给大家一个参考。
疑问,确实像往常一样在service上添加了注解 @Transactional,为什么查询数据库时还是发现有数据不一致的情况,想想肯定是事务没起作用,出现异常的时候数据没有回滚。...于是就对相关代码进行了一番测试,结果发现一下踩进了两个坑,确实是事务未回滚导致的数据不一致。...Service类内部方法调用 大概就是 Service 中有一个方法 A,会内部调用方法 B, 方法 A 没有事务管理,方法 B 采用了声明式事务,通过在方法上声明 Transactional 的注解来做事务管理...对于加了@Transactional注解的方法来说,在调用代理类的方法时,会先通过拦截器TransactionInterceptor开启事务,然后在调用目标类的方法,最后在调用结束后,TransactionInterceptor...在代码中我虽然捕获了异常,但是同时我也抛出了异常,为什么事务未回滚呢?猜测是异常类型不对,于是开始查询原因,翻看了Spring的官方文档,找到了答案。下面是翻译自Spring官网。
如果加了事务,必须做好开发环境测试(测试环境也尽量触发异常、测试回滚),确保事务生效。 C. 以下列了事务使用过程的注意事项,请大家留意。 1....5.经过在ICORE-CLAIM中测试,效果如下: A.抛出受查异常XXXException,事务会回滚。 B.抛出运行时异常NullPointerException,事务会回滚。...(即上文3点提到的) D.异步任务中,execute直接调用加了@Transactional方法,可以回滚;间接调用,不会回滚。...F.在service中加上@Transactional,如果是action直接调该方法,会回滚,如果是间接调,不会回滚。...主要用来配置当前需要执行的方法,与当前是否有transaction之间的关系。 我晓得有点儿抽象,这也是为什么我想要写这篇博客的原因。看了后面的例子,大家应该就明白了。
上周,一同事看到我去年写的一些代码,@Transactional 加上了 rollbackFor,就问我为什么。我当时和他解释了一番,这里我分享出来,希望能够帮助到更多的人。...准备数据 首先我在 Mysql 中准备了一条数据,如下所示: 开始测试 下面我们就开始简单粗暴的测试了。 我们的目的是需要把delflag修改为 0,简单的准备一下 sql。...@Transactional且不加rollbackFor,然后抛出上面的异常时,数据库回滚了。...原因是:@Transactional默认回滚的的异常就RuntimeException类型的。只要是RuntimeException类型的,和它子类型的异常,默认的都能回滚。...这个时候我们去看一下数据库的值到底有没有修改成功,很显然数据是被回滚了。并没有修改成0。 下面我们再试试@Transactional不能回滚的异常。
为何要进行弱网测试 我当前所在项目的产品是一款适配于低资源环境的医疗IT系统,目前主要是在坦桑尼亚地区使用。...弱网测试时碰到的问题和解决方案 1、现象:用户登录应用时下载初始化数据,下载过程中因网速太慢点击取消并重新登录,数据初始化完成后出现重复,造成数据不一致。...原因:数据下载过程中、下载失败后,未进行数据回滚,中止后重新下载,出现数据重复。 解决方案 :通过事务处理数据下载逻辑,下载失败后,应用本地数据库进行数据回滚。...5、现象:弱网络环境下,用户请求页面响应时间较长,等待的过程中,页面上的部分控件仍然可以操作,当用户点击控件时,出现应用闪退现象; 原因:没有对数据加载流程进行判断,直接暴露控件可控,当出现依赖数据的控件操作时...6、现象:在弱网环境下,用户第一次输入搜索关键字没有得到响应后,再次输入全新关键字并发送请求,等待搜索结果返回后,当前结果页被之前的关键字搜索结果刷新覆盖。
..... } 再次测试:发生异常的情况下,数据依然没有回滚!...这又是为什么呢? 原因在于:注解方式的事务声明@Transactinal是基于AOP的,而AOP的底层是通过动态代理模式来实现,也就是说事务的回滚逻辑其实是存在于代理类的方法增强逻辑中。...坑点:声明事务的方法在发生指定抛出的异常类型时,事务无法回滚。...解决方案:在@Transactional注解中声明事务回滚支持的异常类型 @Transactional(rollbackFor = Exception.class) 3 嵌套事务的回滚逻辑错误...public boolean insertLog(){ logDao.insertLog(); } } 通过代码可以看到,我在主事务方法中包含了日志入库的子事务方法,那么当子事务回滚,
..... } 再次测试:发生异常的情况下,数据依然没有回滚!...这又是为什么呢? 原因在于:注解方式的事物声明@Transactinal是基于AOP的,而AOP的底层是通过动态代理模式来实现,也就是说事物的回滚逻辑其实是存在于代理类的方法增强逻辑中。...坑点:声明事物的方法在发生指定抛出的异常类型时,事物无法回滚。...解决方案:在@Transactional注解中声明事物回滚支持的异常类型 @Transactional(rollbackFor = Exception.class) 3 嵌套事物的回滚逻辑错误...public boolean insertLog(){ logDao.insertLog(); } } 通过代码可以看到,我在主事物方法中包含了日志入库的子事物方法,那么当子事物回滚,
既然发生了问题,那么必然是要总结和反省的,然后我今天这里有时间总结一下各种事务失效的问题。...a方法抛出异常后,b方法并没有进行回滚,因为Propagation.REQUIRES_NEW会暂停 a方法的事务 ) Propagation.NOT_SUPPORTED:以非事务的方式运行,如果当前存在事务...如果超过该时间限制但事务还没有完成,则自动回滚事务。...之所以会失效是因为在Spring AOP 代理时,如上图所示 TransactionInterceptor (事务拦截器)在目标方法执行前后进行拦截,DynamicAdvisedInterceptor(...,但是事务并没有回滚。
如上图,在新增卡片时,先做了数据库的插入,然后做ES的插入,最后做事件的通知及其他操作。看着好像也没什么问题。 等等,不对,为什么这里没做事务管理?如果有事务,失败了不就会回滚么?...看来问题的根源找到了: 用户在操作新增卡片时,先往数据库插了条数据,然后ES上也增加了对应的数据,但是在做事件更新时,出了问题(第1步的报错信息来源于此),触发了@Transactional事务回滚的机制...但是由于ES不支持事务,所以@Transactional也没办法回滚,所以列表中的数据还是能被查看到(第2步,ES中的数据还是在的),但是点击详情(第3步)时,因为在数据库中找不到对应的数据,所以页面无法显示...在异常类中统一处理,如果发现这个方法有异常抛出,就记录数据信息,去ES中做对应的回退操作(分类处理,例如数据库是insert操作,就调用ES的delete操作数据删除),人为实现ES的回滚; 3....对于事务的一致性测试,在平时很容易被忽略,大家都还是相信开发会使用事务的。但是对于事务管理是否会失效,没有引起足够的重视。 对于测试人员而言,常见的事务一致性测试场景有哪些呢? a.
事务在执行过程中发生错误,会被回滚(Rollback)到事务开始前的状态,就像这个事务从来没有执行过一样。 一致性(Consistency):在事务开始之前和事务结束以后,数据库的完整性没有被破坏。...不可重复读是指,在一个事务内,多次读同一数据,在这个事务还没有结束时,如果另一个事务恰好修改了这个数据,那么,在第一个事务中,两次读取的数据就可能不一致。...幻读是指,在一个事务中,第一次查询某条记录,发现没有,但是,当试图更新这条不存在的记录时,竟然能成功,并且,再次读取同一条记录,它就神奇地出现了。...事务的超时时间 事务超时,也就是指一个事务所允许执行的最长时间,如果在超时时间内还没有完成的话,就自动回滚。...事务的回滚策略 默认情况下,事务只在出现运行时异常(Runtime Exception)时回滚,以及 Error,出现检查异常(checked exception,需要主动捕获处理或者向上抛出)时不回滚
NESTED NESTED 也是常用的一个传播类型,该方法的特性与 REQUIRED 非常相似,其特性是:当前方法存在事务时,子方法加入在嵌套事务执行。当父方法事务回滚时,子方法事务也跟着回滚。...而 REQUIRED 则是:父方法发生异常回滚时,子方法事务会回滚。而子方法事务发送回滚时,父事务是否回滚取决于是否捕捉了异常。 为了验证 NESTED 事务传播类型的特点,我们来做几个测试。...这说明父方法发送异常时,子方法事务会回滚。 接着,我们继续验证一下:当子方法事务发生异常时,如果父方法没有捕捉异常,父方法事务是否会回滚?...这说明子方法发送异常回滚时,如果父方法没有捕捉异常,那么父方法事务也会回滚。 最后,我们验证一下:当子方法事务发生异常时,如果父方法捕捉了异常,父方法事务是否会回滚?...此时父子方法的事务时独立的,它们都不会相互影响。但父方法需要注意子方法抛出的异常,避免因子方法抛出异常,而导致父方法回滚。 NESTED 当前方法存在事务时,子方法加入在嵌套事务执行。
事务传播行为是指多个拥有事务的方法在嵌套调用时的事务控制方式 比如XML中配置:XML: 注解配置:@Transactional...疑问:异常继续往上抛父方法才知道发生了异常,导致方法里所有数据库操作回滚,那么我把这个异常try-catch,是不是就只有saveChildren()回滚呢?那可不一定,跟着我继续来看。...saveChildren()产生的异常被捕获,没有继续上抛,父方法开启的事务不会回滚,故插入2条数据。...子方法saveChildren()支持父事务,故使用事务,saveChildren()发生异常回滚,这里子事务没将父事务挂起,子事务回滚,父事务一定回滚,正好验证了前面说过的结论,所以这里没有记录...原来的事务都挂起了,子事务回滚和父事务回滚没有必然联系了。 其实这里原因是因为异常抛给了父事务,导致回滚。
但根据之前的分析我们知道,实际上在调用saveB方法时,是直接调用的目标类中的saveB方法,在saveB方法前后并不会有事务的开启或者提交、回滚等操作,实际的流程是下面这样的 ?...如果你看过我之前的源码分析的文章应该知道,在处理回滚时有这么一段代码 ? rollBackOnly设置 在提交时又做了下面这个判断(这个方法我删掉了一些不重要的代码) ?...当传播级别为requires_new时,两个事务完全没有联系,各自都有自己的事务管理机制(开启事务、关闭事务、回滚事务)。...但是传播级别为nested时,实际上只存在一个事务,只是在调用a方法时设置了一个保存点,当a方法回滚时,实际上是回滚到保存点上,并且当外部事务提交时,内部事务才会提交,外部事务如果回滚,内部事务会跟着回滚...显示回滚 最大的区别在于处理回滚时第二个参数传入的是false,这意味着回滚是回滚是预期之中的,所以在处理完回滚后并不会抛出异常。
在目标方法执行前加入或创建一个事务,在执行方法执行后,根据实际情况选择提交或是回滚事务。 使用这种方式,对代码没有侵入性,方法内只需要写业务逻辑就可以了。...saveB(B b){ dao.saveB(a); } } 实际上在调用 saveB 方法时,是直接调用的目标类中的 saveB 方法,在 saveB 方法前后并不会有事务的开启或者提交、回滚等操作...如果你看过我之前的源码分析的文章应该知道,在处理回滚时有这么一段代码 rollBackOnly 设置 在提交时又做了下面这个判断(这个方法我删掉了一些不重要的代码) commit_rollbackOnly...但是传播级别为 nested 时,实际上只存在一个事务,只是在调用 a 方法时设置了一个保存点,当 a 方法回滚时,实际上是回滚到保存点上,并且当外部事务提交时,内部事务才会提交,外部事务如果回滚,内部事务会跟着回滚...这样当提交事务时会进入下面这段代码 显示回滚 最大的区别在于处理回滚时第二个参数传入的是 false, 这意味着回滚是回滚是预期之中的,所以在处理完回滚后并不会抛出异常。
事务失效了,这一次的userDao是自己创建的实例,而不是动态代理类。 动态代理类,在使用@Transactional的方法时,前置通知开启事务,后置通知决定是提交还是回滚。...2)修饰在非public方法上时 如果@Transactional修饰在非public修饰的方法上,事务将会失效。...在使用@Transactional时,使用到public的方法上。所以这也是我不建议将注解使用在类上的原因,你以为类中的方法都有事务了,但实际不然。...} /** * 外部方法没有事务,内部方法会创建一个新的事务 * 如果发生异常,只会导致自己所在的方法事务回滚 * 这里创建了两个事务 */...我们将外部方法的事务称为父事务,内部方法创建的事务为子事务 当子事务回滚时,不影响父事务 当父事务回滚时,子事务一起回滚 这里同样,我们来进行测试一下 package com.banmoon.test.service
测试该事务是否回滚:若发现用户名=JavaEdge,抛异常,触发事务回滚。...测试保存我这个用户: 执行结果打印出了这样的信息: 异常抛了,但观察到DB还是有条新记录。 那为何异常也抛了,却没有回滚?...条件满足时,即会触发事务回滚。...DefaultTransactionAttribute 的 rollbackOn() 当发生如下 case: 没有在 @Transactional 配置 rollback 属性 或者,捕获到的异常和所配置异常类型不一...: 综上,Spring 处理事务时,若没有在 @Transactional 配置 rollback 属性,则只有捕获到 RuntimeException 或 Error 才会触发事务回滚。
,导致事务没开启,因此在方法抛出异常时,testMapper.insert(new Test(10,20,30));操作不会进行回滚。...} } 上面就是使用的测试代码,运行测试知道,外部调用事务方法能够征程开启事务,testMapper.insert(new Test(10,20,30))操作将会被回滚; 然后运行另外一个测试用例,调用一个方法在类内部调用内部被...第三种 事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。 示例代码如下。...,虽然抛出异常,但是异常被捕捉了,没有抛出到方法 外, testMapper.insert(new Test(210,20,30))操作并没有回滚。...~ 第三种 事务方法内部捕捉了异常,没有抛出新的异常,导致事务操作不会进行回滚。
领取专属 10元无门槛券
手把手带您无忧上云