事务作用:在数据层保障一系列的数据库操作一致性(同时成功,同时失败)
Spring事务作用:在 数据层 或 业务层 保障一系列的数据库操作同时成功同时失败
案例1:模拟银行账号间转账
A账户减钱,B账户加钱
那么什么是“同时成功、同时失败”呢?
“A账户减钱操作”后,出现了异常,导致“B账号加钱操作”不能正常执行。那么此时A操作成功B操作失败就不是“同时成功同时失败”。
即:异常之前操作成功,异常之后操作失败,整体业务失败。
1 配置当前接口方法具有事务
@Transactional
Transactional [træn'zækʃənəl] adj. 相互作用的;事务性的,事务处理的
//AccountService.java
@Transactional
public void transfer(String out,String in ,Double money);
或
//直接写在接口上
@Transactional
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
public void transfer(String out,String in ,Double money) ;
}
2 配置事务管理器
//JdbcConfig.java
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
事务管理器要根据技术进行选择。例,MyBatis框架使用的是JDBC事务
PlatformTransactionManager:Spring提供的标准接口
DataSourceTransactionManager:JDBC事务(可换)
注入参数DataSource dataSource
3 开启注解式事务驱动
@EnableTransactionManagement
...
@EnableTransactionManagement
public class SpringConfig {
}
Code
//AccountServiceImpl.java
@Transactional
public void transfer(String out,String in ,Double money) {
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}
//AccountDao.java
@Update("update tbl_account set money = money + #{money} where name = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update tbl_account set money = money - #{money} where name = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
事务角色
在没有开启Spring事务前,outMoney和inMoney都会“开启事务”,但是开启的事务不同:开启事务T1、开启事务T2
开启Spring事务后(开启事务T)【事务管理员】,两个操作加入事务T中【事务协调员】
事务管理员
发起事务方。在Spring中通常指 业务层 开启事务的方法
事务协调员
加入事务方。在Spring中指代 数据层 方法,也可以是 业务层 方法
事务相关配置
1readOnly = true1:只读事务
1timeout = -11:永不超时
@Transactional(readOnly = true, timeout = -1)
1rollbackFor1:设置事务的回滚异常
有些异常(IOExceprtion)不会触发回滚,得手动加上
@Transactional(rollbackFor = IOException.class)
案例2:log
事务传播行为:事务协调员 对事务管理员 所携带事务的处理态度。
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)