新博客:https://blog.bigdataboy.cn/article/453.html
什么是事务
事务是
逻辑
上的一组操作
,主要是对数据库
的数据的操作
,要么都执行
,要么都不执行
,重点是都
,所以当这组操作不一致
时,那么就自动进行回滚
,把数据恢复
到这组操作之前
,这样数据库的数据
就不会出错了
。
转账案例
事务这个概念最早是在 数据库 接触到,但是感觉并不明显,这里可以通过这个案例感受一下
a 给 b 转账 100
正常情况
- a 的 余额 减少 100
- b 的 余额 增加 100
public void transfer(String out, String in, Double money) {
// 转账
accountDao.inMoney(in, money);
accountDao.outMoney(out, money);
}
如果在转账过程中出现异常,不使用事务的话,就会出现,
一方钱减少了
,而另一方确没有增加
public void transfer(String out, String in, Double money) {
// 转账
accountDao.inMoney(in, money);
// 期间出现报错
accountDao.outMoney(out, money);
}
Spring 事务处理
第一步、定义该函数需要
事务处理
,在接口上定义
项目使用的 DataSource 要一样,不然事务无法实现,案例中指 MyBatis 初始化 SqlSessionFactoryBean 时传入的 DataSource 和 JDBC 交给 Spring 的事务的 DataSource 一致
public interface AccountService {
@Transactional // 该注解 开启事务
public void transfer(String out, String in, Double money);
}
第二步、在
JdbcConfig
类,定义事务管理 Bean
交给 Spring 容器管理
@Configuration
public class JdbcConfig {
@Value("${jdbc.driver}")
public String driverClassName;
@Value("${jdbc.url}")
public String url;
@Value("${jdbc.username}")
public String username;
@Value("${jdbc.password}")
public String password;
@Bean
public DataSource dataSource() {
DruidDataSource dataSource = new DruidDataSource();
dataSource.setDriverClassName(driverClassName);
dataSource.setUrl(url);
dataSource.setUsername(username);
dataSource.setPassword(password);
return dataSource;
}
@Bean // 把事务管理器交给 Spring 管理
public DataSourceTransactionManager dataSourceTransactionManager(DataSource dataSource) {
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
第三步、在 SpringConfig
使用注解开启事务
@Configuration
@ComponentScan({"cn.bigdataboy"})
@PropertySource({"classpath:jdbc.properties"})
@Import({MyBatisConfig.class, JdbcConfig.class})
@EnableTransactionManagement // 开启事务管理器
public class SpringConfig {
}
测试
注意 默认状态
下并不是所有的异常都会回滚
,可以通过 事务属性 进行控制
事务角色
在上述案例中,
小事务一 和 二 (事务协调员)
会被加入到大的事务(事务管理员)
,由事务管理员
统一管理
事务管理员:在 Spring 中通常指 开启事务的方法
事务协调员:在 Spring 中通常指 数据层方法,也可以是业务层方法
事务的属性
事务的属性能使
事务管理员
对事务协调员
精细化的管理
属性 | 作用 | 实例 |
---|---|---|
readOnly | 设置是否为只读事务 | readOnly=true 只读事务 |
timeout | 设置事务超时时间 | timeout = -1 (永不超时) |
rollbackFor |
设置事务回滚异常(class) | rollbackFor = {NullPointerException.class} |
rollbackForClassName | 设置事务回滚异常(String) | 同上,只是参数为字符串 |
noRollbackFor | 设置事务不回滚异常(class) | noRollbackFor = {NullPointerException.class} |
noRollbackForClassName | 设置事务不回滚异常(String) | 同上,只是参数为字符串 |
propagation | 事务传播 | 见下面 |
事务传播
默认情况下,发送错误时,子事务全部都要回滚,那有一些事务是不需要回滚(记录日志到数据库),这也是需要实现的,子事务
可以控制
自己是否需要主事务
控制。
public interface AccountLogService {
@Transactional(propagation = Propagation.REQUIRES_NEW) // 该注解 开启事务
public void add(String out, String in, Double money);
}
propagation 参数说明
(T 代表事务)传播属性 |
事务管理员 | 事务协调员 |
---|---|---|
REQUIRED (默认) |
开启 T / 无 | 加入 T / 新建 T2 |
REQUIRES_NEW |
开启 T / 无 | 新建 T2 / 新建 T2 |
SUPPORTS |
开启 T / 无 | 加入 T / 无 |
NOT_SUPPORTED |
开启 T / 无 | 无 / 无 |
MANDATORY |
开启 T / 无 | 加入 T / ERROR |
NEVER |
开启 T / 无 | ERROT / 无 |
NESTED |
开启 T / 无 | 设置 savePoint,一但事务回滚,事务将回滚到 savaPoint 处,交由客户端提交/回滚 |
版权声明:《 【Spring】核心概念:事务 》为明妃原创文章,转载请注明出处!
最后编辑:2022-10-4 13:10:21