Spring事务
Spring事务是在所使用的数据库事务的基础上进行封装扩展
封装主要是封装了一些JDBC的一写事务操作的对象, 扩展主要有以下几点特性
- 加入了事务传播的概念, 从代码逻辑上看来比编程式事务简化很多
- 提供声明式事务或者是注解式配置事务,让业务代码与事务分离,事务变得更易用(AOP技术)
但是也造成了事务失效的情况出现, 具体原因下面讲述
事务API
Spring提供了一个TransactionDefinition, 它定义了事务的隔离级别和传播特性
隔离级别默认是DEFAULT也就是默认是数据库的隔离级别
传播特性默认是required表示有就加入没有就创建
还专门定义了一个事务管理器PlatformTransactionManager, 提供了事务的commit提交和rollback回滚操作, 还有获取此时事务状态的一个方法
事务的状态有以下几个
顾名思义吧, 比如是否是新建的事务, 是否已经提交, 是否已经回滚, 是否完成
还有一个最重要的TransactionInterceptor, 而TransactionInterceptor实现了MethodInterceptor, 表示方法拦截, 当我们要执行配置了事务的方法的时候就会进行方法的拦截,拦截到配置了事务的方法之后就会在TransactionAspectSupport下, 对其信息一些加强处理(AOP)
大多情况使用注解**@Transactional**实现事务支持的话很方便, 可以配置一些属性
-
name
当在配置文件中有多个TransactionManager,可以用该属性指定选择哪个事务管理器。 -
propagation
事务的传播行为,默认值为 REQUIRED。 -
isolation
事务的隔离度,默认值采用DEFAULT。 -
timeout
事务的超时时间,默认值为-1。如果超过该时间限制但事务还没有完成,则自动回滚事务。 -
read-only
指定事务是否为只读事务,默认值为false;为了忽略那些不需要事务的方法,比如读取数据,可以设置read-only为true。 -
rollback-for
用于指定能够触发事务回滚的异常类型,如果有多个异常类型需要指定,各类型之间可以通过逗号分隔。 -
no-rollback-for
抛出no-rollback-for指定的异常类型,不回滚事务。
实现原理
这个的实现原理还是动态代理的方式实现, 基于CGLib动态代理, 核心就是使用拦截器。它就是TransactionInterceptor。
TransactionInterceptor实现了MethodInterceptor, 所以被@Transactional注解的方法会被TransactionInterceptor拦截, 然后invoke方法被调用根据@Transactional配置的属性初始化TransactionDefinition, TransactionManager会更具属性的判断是get还是new一个这个就是根据事务的传播特性去查, TransactionManager有个方法就是为了获得此时事务的状态, 也可以方便去判断是,最终会调用TransactionAspectSupport方法实现增强.
事务失效
bean是否被Spring托管, 或者Bean是否被代理
方法是否是public的
数据库是否支持事务
方法是不是被static或者final修饰
是否是方法内部调用导致的事务失效
异常是否被catch了
异常是否符合规范, 默认是runtimeException
事务传播机制
- 常用的事务传播机制
PROPAGATION_REQUIRED
这个也是默认的传播机制;
PROPAGATION_REQUIRES_NEW
总是新启一个事务,这个传播机制适用于不受父方法事务影响的操作
比如某些业务场景下需要记录业务日志,用于异步反查,那么不管主体业务逻辑是否完成,日志都需要记录下来,不能因为主体业务逻辑报错而丢失日志;
PROPAGATION_NOT_SUPPORTED
不使用事务, 有事务就挂起
可以用于发送提示消息,站递信、短信、邮件提示等。不属于并且不应当影响主体业务逻辑,即使发送失败也不应该对主体业务逻辑回滚。