Spring事务
一、Spring事务简介
- 事务作用:在数据层保障一系列的数据库操作同成功同失败。
- Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败。
(1)接口
(2)实现类
二、案例:银行账户转账
2.1 业务分析
2.2 实例
2.2.1 在业务层接口上添加Spring事务管理
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
//配置当前接口方法具有事务
@Transactional
public void transfer(String out,String in ,Double money) ;
}
- 注意事项:Spring注解式事务通常添加在业务层接口中而不会添加到业务层实现类中,降低耦合。
- 注解式事务可以添加到业务方法上表示当前方法开启事务,也可以添加到接口上表示当前接口所有方法开启事务。
2.2.2 设置事务管理器
public class JdbcConfig {
@Value("${jdbc.driver}")
private String driver;
@Value("${jdbc.url}")
private String url;
@Value("${jdbc.username}")
private String userName;
@Value("${jdbc.password}")
private String password;
@Bean
public DataSource dataSource(){
DruidDataSource ds = new DruidDataSource();
ds.setDriverClassName(driver);
ds.setUrl(url);
ds.setUsername(userName);
ds.setPassword(password);
return ds;
}
//配置事务管理器,mybatis使用的是jdbc事务
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource){
DataSourceTransactionManager transactionManager = new DataSourceTransactionManager();
transactionManager.setDataSource(dataSource);
return transactionManager;
}
}
- 注意事项:事务管理器要根据实现技术进行选择
- MyBatis框架使用的是JDBC事务。
2.2.3 开启注解式事务驱动
@Configuration
@ComponentScan("com.itheima")
@PropertySource("classpath:jdbc.properties")
@Import({JdbcConfig.class,MybatisConfig.class})
//开启注解式事务驱动
@EnableTransactionManagement
public class SpringConfig {
}
2.3 总结
三、Spring事务角色
3.1 事务管理员
- 发起事务方,在Spring中通常指代业务层开启事务的方法。
3.2 事务协调员
- 加入事务方,在Spring中通常指代数据层方法,也可以是业务层方法。
四、Spring事务属性
4.1 事务配置
4.1.1 使用rollbackFor属性来设置出现IOException异常不回滚
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Transactional(rollbackFor = {IOException.class})
public void transfer(String out,String in ,Double money) throws
IOException{
accountDao.outMoney(out,money);
//int i = 1/0; //这个异常事务会回滚
if(true){
throw new IOException(); //这个异常事务就不会回滚
}
accountDao.inMoney(in,money);
}
}
4.2 案例:转账业务追加日志
4.2.1 案例分析
4.2.2 创建日志表
create table tbl_log(
id int primary key auto_increment,
info varchar(255),
createDate datetime
)
4.2.3 添加LogDao接口
public interface LogDao {
@Insert("insert into tbl_log (info,createDate) values(#{info},now())")
void log(String info);
}
4.2.4 添加LogService接口与实现类
public interface LogService {
void log(String out, String in, Double money);
}
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
@Transactional
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
4.2.5 在转账的业务中添加记录日志
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
//配置当前接口方法具有事务
public void transfer(String out,String in ,Double money)throws
IOException ;
}
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
@Autowired
private LogService logService;
@Transactional
public void transfer(String out,String in ,Double money) {
try{
accountDao.outMoney(out,money);
accountDao.inMoney(in,money);
}finally {
logService.log(out,in,money);
}
}
}
4.3 事务传播行为
- 事务传播行为:事务协调员对事务管理员所携带事务的处理态度。
- 如果要实现“不管转账是否成功,都会记录日志”。可以修改logService改变事务的传播行为。
4.3.1 修改logService改变事务的传播行为
@Service
public class LogServiceImpl implements LogService {
@Autowired
private LogDao logDao;
//propagation设置事务属性:传播行为设置为当前操作需要新事务
@Transactional(propagation = Propagation.REQUIRES_NEW)
public void log(String out,String in,Double money ) {
logDao.log("转账操作由"+out+"到"+in+",金额:"+money);
}
}
Comments | NOTHING