个人专题目录
1.6. 声明式事务
如果需要某一组操作具有原子性,就用注解的方式开启事务,按照给定的事务规则来执行提交或者回滚操作,事务管理一般在Service层。
-
事务控制
- 编程式事务控制
- Conn.setAutoCommite(false); // 设置手动控制事务
- 粒度较细,比较灵活,但开发起来比较繁琐: 每次都要开启、提交、回滚
- 声明式事务控制
- Spring提供对事务的控制管理
- 编程式事务控制
-
事务属性
- 事务传播行为
- required_new
- 如果当前方法有事务了,当前方法事务会挂起,在为加入的方法开启一个新的事务,直到新的事务执行完、当前方法的事务才开始
- required(默认方法)
- 如果当前方法已经有事务了,加入当前方法事务
- 事务传播行为用来描述由某一个事务传播行为修饰的方法被嵌套进另一个方法的时候事务如何传播。
- required_new
- 数据库隔离级别
- TransactionDefinition.ISOLATION_DEFAULT: 使用后端数据库默认的隔离级别,Mysql 默认采用的 REPEATABLE_READ隔离级别 Oracle 默认采用的 READ_COMMITTED隔离级别.
- TransactionDefinition.ISOLATION_READ_UNCOMMITTED: 最低的隔离级别,允许读取尚未提交的数据变更,可能会导致脏读、幻读或不可重复读
- TransactionDefinition.ISOLATION_READ_COMMITTED: 允许读取并发事务已经提交的数据,可以阻止脏读,但是幻读或不可重复读仍有可能发生
- TransactionDefinition.ISOLATION_REPEATABLE_READ: 对同一字段的多次读取结果都是一致的,除非数据是被本身事务自己所修改,可以阻止脏读和不可重复读,但幻读仍有可能发生。
- TransactionDefinition.ISOLATION_SERIALIZABLE: 最高的隔离级别,完全服从ACID的隔离级别。所有的事务依次逐个执行,这样事务之间就完全不可能产生干扰,也就是说,该级别可以防止脏读、不可重复读以及幻读。但是这将严重影响程序的性能。通常情况下也不会用到该级别。
- 事务超时属性
- 指一个事务所允许执行的最长时间,如果超过该时间限制但事务还没有完成,则自动回滚事务。
- 事务只读属性
- 对事物资源是否执行只读操作
- 回滚规则
- 定义了哪些异常会导致事务回滚而哪些不会。默认情况下,事务只有遇到运行期异常时才会回滚,而在遇到检查型异常时不会回滚,也可以用用户自己定义
- 事务传播行为
-
Spring事务管理接口
- PlatformTransactionManager
- (平台)事务管理器
Spring并不直接管理事务,而是提供了多种事务管理器,通过PlatformTransactionManager这个接口,Spring为各个平台如JDBC、Hibernate等都提供了对应的事务管理器,但是具体的实现就是各个平台自己的事情了。
- TransactionDefinition
- 事务定义属性(事务隔离级别、传播行为、超时、只读、回滚规则)
- TransactionStatus
- 事务运行状态
- PlatformTransactionManager
-
事务管理一般在Service层
- 如果在dao层,回滚的时候只能回滚到当前方法,但一般我们的service层的方法都是由很多dao层的方法组成的
- 如果在dao层,commit的次数会过多
环境搭建:
- 导入相关依赖 数据源、数据库驱动、Spring-jdbc模块
- 配置数据源、JdbcTemplate(Spring提供的简化数据库操作的工具)操作数据
- 给方法上标注 @Transactional 表示当前方法是一个事务方法;
- @EnableTransactionManagement 开启基于注解的事务管理功能;
- 配置事务管理器来控制事务;
@EnableTransactionManagement
@ComponentScan("com.xubh.tx")
@Configuration
public class TxConfig {
//数据源
@Bean
public DataSource dataSource() throws Exception {
ComboPooledDataSource dataSource = new ComboPooledDataSource();
dataSource.setUser("root");
dataSource.setPassword("123456");
dataSource.setDriverClass("com.mysql.jdbc.Driver");
dataSource.setJdbcUrl("jdbc:mysql://localhost:3306/test");
return dataSource;
}
//
@Bean
public JdbcTemplate jdbcTemplate() throws Exception {
//Spring对@Configuration类会特殊处理;给容器中加组件的方法,多次调用都只是从容器中找组件
JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource());
return jdbcTemplate;
}
//注册事务管理器在容器中
@Bean
public PlatformTransactionManager transactionManager() throws Exception {
return new DataSourceTransactionManager(dataSource());
}
}
@EnableTransactionManagement
- @EnableTransactionManagement原理
- 利用TransactionManagementConfigurationSelector给容器中会导入组件,导入两个组件AutoProxyRegistrar和ProxyTransactionManagementConfiguration
- AutoProxyRegistrar:
- 给容器中注册一个 InfrastructureAdvisorAutoProxyCreator 组件;
- InfrastructureAdvisorAutoProxyCreator:?
- 利用后置处理器机制在对象创建以后,包装对象,返回一个代理对象(增强器),代理对象执行方法利用拦截器链进行调用;
- ProxyTransactionManagementConfiguration 做了什么?
- 给容器中注册事务增强器;
- 事务增强器要用事务注解的信息,AnnotationTransactionAttributeSource解析事务注解
- 事务拦截器:TransactionInterceptor;保存了事务属性信息,事务管理器;他是一个 MethodInterceptor;在目标方法执行的时候;执行拦截器链;事务拦截器:
- 先获取事务相关的属性
- 再获取PlatformTransactionManager,如果事先没有添加指定任何transactionmanger,最终会从容器中按照类型获取一个PlatformTransactionManager;
- 执行目标方法;如果异常,获取到事务管理器,利用事务管理回滚操作;如果正常,利用事务管理器,提交事务
- 给容器中注册事务增强器;