Java之事务的基本应用

基本介绍

  事务是数据一致性最基本的保证,也就是说一个事务中的操作要么都成功,要么都失败,不允许部分成功。我们常说的事务就是jdbc事务,当然Java中还有其他事务,并且在使用jdbc事务有很多注意点,请详细了解“注意点”中的内容。但是这里有个误区,因为我们一般是使用spring的注解@Transactional来实现事务,所以很多人会认为spring提供了事务,其实spring本身并没有提供事务,它只是对jdbc的事务进行了封装,然后通过AOP动态代理来实现事务的功能,这样简化了jdbc事务调用的相关步骤,让我们更专注于业务功能。

  注意关键词“动态代理”,这意味着要生成一个代理类,那么我们就不能在一个类内直接调用事务方法,否则无法代理,而且该事务方法必须是public,如果定义成 protected、private 或者默认可见性,则无法调用!

实现原理

注意点(容易引起事务不生效)

  • 使用的数据库引擎是否支持事务
  • 加事务的方法必须是public,否则事务不起作用(这一点由Spring的AOP特性决定的,理论上而言,不public也能切入,但spring可能是觉得private自己用的方法,应该自己控制,不应该用事务切进去吧)。另外private 方法, final 方法 和 static 方法不能添加事务,加了也不生效
  • 处理的业务和事务的入口必须在一个线程内,否则事务不生效
  • 对于jdbc事务而言,必须是一个connection中才有效的
  • Spring的事务管理默认只对出现运行期异常(java.lang.RuntimeException及其子类)进行回滚(至于为什么spring要这么设计:因为spring认为Checked的异常属于业务的,coder需要给出解决方案而不应该直接扔该框架)。如果业务需要,一定要抛出checked异常的话,可以通过rollbackFor属性指定异常类型即可。
  • 确认调用的类是否倍贷理了
  • 在本类中调用另一个带有事务的方法,事务时不生效的。这个时最容易犯的错误,不生效的原因主要是和事务的实现原理有关
  • @EnableTransactionManagement // 启注解事务管理,等同于xml配置方式的 <tx:annotation-driven />备注:本系列所有博文的讨论都针对于springboot而不再对spring做说明

类型

  • JDBC事务
  • JAT事务
  • 容器事务

特性

基本场景

图一:事务不生效:.@Transactional的事务开启 ,或者是基于接口的 或者是基于类的代理被创建。所以在同一个类中一个无事务的方法调用另一个有事务的方法,事务是不会起作用的(这就是业界老问题:类内部方法调用事务不生效的问题原因)。

 

图二:事务生效

图三:事务生效

 

图四:事务生效

 

图五:事务生效(稍微解释一下,这里虽然是方法内部调用,但是事务切入了addInfo方法,所以即使内部抛出异常,也是可以生效的。当年我竟然惊讶,看来还是太年轻,哈哈)

 

图六:事务不生效(准确的说这叫没有事务)

图七:如何使本类中调用方法的事务生效。

  这是我们解决方法内部调用事务不生效的最常用方法之一:内部维护一个注入自己的Bean,然后使用这个属性来调用方法。其实还有一种方法,那就是利用Aop上下文来获取代理对象(((TestService)AopContext.currentProxy()).create(); ),然后通过代理对象来调用。这里需要注意:Aop上下文spring默认是关闭的,需要手动开启

 

嵌套事务

学习链接

jdbc事务和JAT事务管理

spring事务和JDBC事务的关系

猜你喜欢

转载自www.cnblogs.com/htyj/p/10305780.html