spring 的声明式事务注解@Transactional,只在抛出RuntimeException异常的时候,才会回滚。只抛出普通Exception的话,不会回滚。如:
@Transactional public void upgradeTalent(User user, Date updateAt) throws Exception { TalentLevel levelOne = talentLevelService.getTalentLevel(1); long levelId = levelOne.getTalentLevelId(); user.setTalentLevelId(levelId); user.setUpdateAt(updateAt); user.setUpdateBy(user.getUserId()); user.setUpdateType(1); //前台更新类型 int beans = levelOne.getBeans(); user.setBeans(user.getBeans() + beans); userService.updateField(user,"talentLevelId,updateAt,updateBy,updateType,beans"); Integer.parseInt("fsdf"); // throw new Exception("非运行期的普通异常"); Talent talent = new Talent(); talent.setCreateAt(updateAt); talent.setUserId(user.getUserId()); talent.setTalentLevelId(levelId); talent.setUpdateAt(updateAt); talent.setUpdateBy(talent.getTalentId()); talent.setUpdateType(1);//前台更新类型 talent.setLastUpgradeAt(updateAt); long talentId = creat(talent); }
这个upgradeTalent方法以 Integer.parseInt("fdfs")为界,分为两个事务,userService.updateField和creat(talent),整个upgradeTalent方法加了注解,是一个大事务,要么userService.updateField和creat(talent)同时成功,要么同时失败。
上面的Integer.parseInt("fdfs")方法会抛出NumberFormatException,这个异常是RuntimeException的一个子类,所以事务会回滚,没有更新到User表和Talent表。如果这时候把上面Integer.parseInt("fdfs")改为手动抛出一个非RuntimeException,如改成:throw new Exception("普通异常"),当方法执行到抛出异常这行代码时,即使整个方法加了@Transactional的注解,事务也不会回滚,user表已经被更新,造成脏数据。
所以,在使用spring @Transactional注解的时候,要注意一下。
另外,用Integer.parseInt("fdfs")这句代码,是为了验证发生异常后事务回滚的问题,实际情况可能是其它原因造成异常。
RuntimeException继承Exception
其实Transactional在定义的时候,也说明了事务的使用范围:RetentionPolicy.RUNTIME
@Target({ElementType.METHOD, ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Inherited
@Documented
public @interface Transactional
相关推荐
之后主事务在进行事务提交时,会判断全局回滚标识是否存在。若存在就会进行回滚动作(AbstractPlatformTransactionManager.commit)。 2.2 子事务的传播机制为 REQUIRES_NEW 在这种情况下,子事务异常情况下,主...
Spring事务原理和配置 ...可是如果读者仔细研究了Spring事务管理的代码以后就会发现,事务管理其实也是如此简单的事情。这也印证了在本书开头,Spring事务管理的设计理念是:简洁、灵活、可扩展和可靠的。
在使用Spring的事务管理功能之后,开发者无需手动编写上述事务控制的代码,这些工作将由Spring框架自动完成。具体来说,Spring通过以下步骤实现事务管理: 1. **开启注解驱动**:在配置文件中开启注解驱动,并在...
4. **异常处理不当**:在事务中,只有当方法抛出未被捕获的异常时,Spring才会回滚事务。如果捕获了异常,事务可能不会被回滚。因此,谨慎处理异常,避免错误地捕获并忽略它们。 5. **回调方法中的事务失效**:在...
1. **`PlatformTransactionManager`**:Spring 的核心事务管理接口,用于管理事务的开始、提交或回滚。具体实现由不同的数据库平台提供,如 `DataSourceTransactionManager` 对于 JDBC 数据源,`...
如果这些方法抛出异常,则事务将回滚;否则,事务将在方法成功完成后提交。 ### 第二种方式:使用AOP和AspectJ 第二种方式利用Spring的AOP(面向切面编程)功能,结合AspectJ语法,来定义事务切面。这种方法允许更...
Spring实现的事务本质就是AOP完成,对方法前后进行拦截,在执行方法之前开启事务,在执行完目标方法之后根据执行情况提交或者回滚事务。 事务失效的场景 在项目中,经常会遇到事务失效的场景。例如,如果方法上...
这些注解分别对应五种不同类型的通知,分别在连接点之前、之后、成功返回后、抛出异常后和环绕执行时插入代码。 3. 切入点表达式(Pointcut Expression) 通过正则表达式或预定义的切入点函数,定义哪些连接点会被...
- 虽然Spock框架在Spring 2.5之后才逐渐流行,但通过适配器,也可以与Spring TestContext框架一起使用,提供更丰富的测试语法和功能。 9. **Web应用程序测试**: - Spring 2.5 TestContext框架也支持Web应用程序...
它们分别在匹配的`execution(* com.example.service.*.*(..))`切点(即com.example.service包下的所有方法)之前、正常返回之后和抛出异常之后执行。 **四、配置启用注解AOP** 在Spring配置文件中,我们需要启用...
特别是在存在多层子函数调用的情况下,容易因某个耗时操作(如RPC调用)而导致长事务问题,甚至可能由于外部调用抛出异常而导致事务回滚,从而使数据库中没有相关记录保存。 - **生产环境案例**:在生产环境中,...
- **后置通知(After Advice)**:在目标方法执行之后执行,无论目标方法是否正常返回或抛出异常。通常用于清理工作,如资源释放。例如,使用`@After`注解的方法会在目标方法结束后执行。 - **返回后通知(After ...
3. **异常后通知(After Throwing Advice)**:在目标方法抛出异常后执行。 4. **最终通知(After Advice)**:无论目标方法是否正常执行,都会在方法结束时执行。 5. **环绕通知(Around Advice)**:可以在方法...
- **事务管理**:在方法执行前后自动开始和提交/回滚事务。 - **性能监控**:统计方法执行的时间。 - **权限控制**:在访问资源前进行权限检查。 - **异常处理**:统一捕获和处理异常。 5. **Spring AOP与...
- 如果`proceed()`抛出异常,那么这个异常会被当作环绕通知方法的返回结果,除非在环绕通知中捕获并处理它。 - 环绕通知比其他类型的通知更强大,但也更复杂,使用时需谨慎,避免引入不必要的复杂性。 总结,...
- 事务管理:确保一组操作的原子性,当有异常时进行回滚。 - 权限控制:验证用户是否有权限执行某个操作。 - 性能监控:计算方法的执行时间,用于性能优化。 总结,Spring AOP提供了一种强大的工具,使得我们可以将...
4. **异常后通知(After Throwing Advice)**:在目标方法抛出异常后执行。 5. **环绕通知(Around Advice)**:可以在目标方法执行前后执行自定义逻辑,并控制方法是否执行以及如何执行。 **切入点表达式...
- **异常通知(After Throwing Advice)**: 当目标方法抛出异常时调用的通知。Spring.NET中,你可以实现`IAfterThrowingAdvice`接口来处理这类通知。 - **环绕通知(Around Advice)**: 这是最强大的通知类型,它...