概要:2Spring事务管理接口(隔离级别,传播行为)、3接口介绍、4回滚原理
Spring事务的本质其实就是数据库对事务的支持,没有数据库的事务支持,spring是无法提供事务功能的。对于纯JDBC操作数据库,想要用到事务,可以按照以下步骤进行:
1)获取连接 Connection con = DriverManager.getConnection()
2)开启事务con.setAutoCommit(true/false);
3)执行CRUD 4)提交事务/回滚事务 con.commit() / con.rollback(); 5)关闭连接 conn.close();
1.事物的特性(ACID)
原子性、一致性、隔离性、持久性
2.Spring事务管理接口:
PlatformTransactionManager: (平台)事务管理器
TransactionDefinition: 事务定义信息(事务隔离级别、传播行为、超时、只读、回滚规则)
TransactionStatus: 事务运行状态
2.1PlatformTransactionManager:
Spring不直接管理,提供多种事务管理器,委托给Hibernate或JTA等持久化机制,提供相关平台框架事务实现。 通过org.springframework.transaction.PlatformTransactionManager 接口,为各个平台如JDBC、Hibernate等提供事务管理器,实现就是各平台的事
PlatformTransactionManager接口定义了三个方法:
不同持久层框架所对应的接口实现类:
用JDBC或者iBatis(Mybatis)持久化时,xml配置:
2.2 TransactionDefinition接口:
2.21并发事务带来的问题:(事务隔离级别)
脏读(Dirty read):事务修改,没提交到库,另一个事务访问,用这数据(脏数据:可能不正确)
丢失修改(Lost to modify):事务读时,另一也访该数据,第一个事务改,第二个事务也改。第一个事务丢失
不可重复读(Unrepeatableread):事务内多次读同一数据。事务没结束,另一事务也访问该数据。第一事务中两次读数据之间,第二改事务,导致不一样。 修改时
幻读(Phantom read):与不可重复读类似。事务T1读几行数据,事务T2插入。随后查,T1发现多了不存在的记录,新增或删除时
2.22隔离级别
TransactionDefinition.ISOLATION_DEFAULT:默认隔离级别(用db默认的隔离级别),Mysql 默认REPEATABLE_READ隔离级别 ,Oracle 默认 READ_COMMITTED
1)TransactionDefinition.ISOLATION_READ_UNCOMMITTED:最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
2)TransactionDefinition.ISOLATION_READ_COMMITTED:允许读取并发事务已经提交的数据,阻止脏读,但幻读或不可重复读仍有可能
3)TransactionDefinition.ISOLATION_REPEATABLE_READ:对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
4)TransactionDefinition.ISOLATION_SERIALIZABLE:最高隔离级别,防止脏读、不可重复读以及幻读。
2.23事务传播行为(解决方法间调用事务问题)
事务方法被另一个事务方法调用时,必须如何传播。如:方法可能继续现有事务中运行,也可开启新事务,并在自的事务中运行。TransactionDefinition定义中传播行为常量:
1)TransactionDefinition.PROPAGATION_REQUIRED:如当前存在事务,则加入该事务;没有创建新事务。
2)TransactionDefinition.PROPAGATION_SUPPORTS:如当前存在事务,则加入该事务;没有,以非事务方式继续运行
3)TransactionDefinition.PROPAGATION_MANDATORY:如当前存在事务,则加入该事务;没有则抛异常
不支持当前事务的情况:
TransactionDefinition.PROPAGATION_REQUIRES_NEW:创建新事务,当前存在事务,把当前事务挂起
TransactionDefinition.PROPAGATION_NOT_SUPPORTED:非事务方式运行,当前存在事务,把当前事务挂起
TransactionDefinition.PROPAGATION_NEVER:非事务方式运行,当前存在事务,抛异常
其他情况:
TransactionDefinition.PROPAGATION_NESTED:如果当前存在事务,则创建一个事务作为当前事务的嵌套事务来运行;如果当前没有事务,则该取值等价于TransactionDefinition.PROPAGATION_REQUIRED。
这里需要指出的是,前面的六种事务传播行为是 Spring 从 EJB 中引入的,他们共享相同的概念。而PROPAGATION_NESTED是 Spring 所特有的。以 PROPAGATION_NESTED 启动的事务内嵌于外部事务中(如果存在外部事务的话),此时,内嵌事务并不是一个独立的事务,它依赖于外部事务的存在,只有通过外部的事务提交,才能引起内部事务的提交,嵌套的子事务不能单独提交。如果熟悉 JDBC 中的保存点(SavePoint)的概念,那嵌套事务就很容易理解了,其实嵌套的子事务就是保存点的一个应用,一个事务中可以包括多个保存点,每一个嵌套子事务。另外,外部事务的回滚也会导致嵌套子事务的回滚。
2.24事务超时属性(一个事务允许执行的最长时间)
超时没完成,自动回滚。int表示时间,单位是秒
2.25事务只读属性(对事物资源是否执行只读操作)
以提高事务处理性能。在 TransactionDefinition 中以 boolean 表示
2.26回滚规则(定义事务回滚规则)
定义哪些异常会回滚、哪些不会。默认,运行期异常时会回滚,检查型异常不回滚(与EJB回滚行为一致)
但可声明事务特定检查型异常时,像运行异常那样回滚。还可声明运行异常不回滚
3.TransactionStatus接口介绍
记录事务状态 定义了一组方法,用来获取或判断事务相应状态信息
PlatformTransactionManager.getTransaction(…) 方法返回TransactionStatus 对象。
返回TransactionStatus 对象可能代表新的或已经存在事务(如当前调用堆栈有符合条件事务)。
4、Spring事务回滚底层实现
用TransactionInterceptor方法拦截器实现事务经过以下步骤实现回滚
1)获取事务属性(注解@Transactional的属性)
2)获取事务管理器PlatformTransactionManager
3)获取需要事务的方法名和事务信息
4)创建事务、获取事务
4)目标方法执行
5)事务回滚(如果是嵌套回滚则回滚到保存点)
参考:https://zhuanlan.zhihu.com/p/149409015
另加2:
a方法内调b方法,然后a方法抛出异常导致事务回滚,如何让b方法执行结果不回滚?
B方法事务级别require new,不要写在同一个类aop切不到,想同一个类调用,自己去applicationcontex 拿bean
https://my.oschina.net/xiaolyuh/blog/3109049