事务
事务作用:在数据层保障一系列的数据库操作同成功同失败
Spring事务作用:在数据层或业务层保障一系列的数据库操作同成功同失败
其实简单来说就是,我一段insert命令要执行好几百个参数,然后运行到50个的时候,断电了,担心数据库只保存了我前面50个,相当于这是条没用的数据,然而,事务便帮我们纠正了:如果这一段没运行完就发生错误,那我就全部回滚,整个都先撤回了。
其实,spring拓展了业务层的事务,其实是能保障我们同时的许许多多的数据层处于同一事务状态——因为一个业务层很可能调用了好多的数据层(是为了保障组合功能中事务生效的)
spring提供了这个接口来保障的:
同时,spring提供了这个实现类
案例
模拟银行账户间的转账业务
需求微缩:A账户扣钱,B账户加钱
同时保证:程序出现异常之后,整体业务必须失败
实现
数据库
我们先建好表
use 20220806lige;
drop table if exists tb_account;
create table tb_account
(
id int primary key auto_increment,
username varchar(20),
money double
);
INSERT INTO tb_account
VALUES (1, '张三', 1000);
INSERT INTO tb_account
VALUES (2, '李四', 1000);
配置基本环境
jdbc.properties需要在数据库url参数后面添加:useSSL=false&useServerPrepStmts=true&useUnicode=true&characterEncoding=utf8
整体使用spring整合mybatis+注解开发使用
Dao层接口
@Update("update tb_account set money = money + #{money} where username = #{name}")
void inMoney(@Param("name") String name, @Param("money") Double money);
@Update("update tb_account set money = money - #{money} where username = #{name}")
void outMoney(@Param("name") String name, @Param("money") Double money);
业务层接口很简单:
public interface AccountService {
/**
* 转账操作
* @param out 传出方
* @param in 转入方
* @param money 金额
*/
public void transfer(String out,String in ,Double money) ;
}
实现类也很简单:
@Service
public class AccountServiceImpl implements AccountService {
@Autowired
private AccountDao accountDao;
public void transfer(String out,String in ,Double money) {
//A转出money
accountDao.outMoney(out,money);
//B转入money
accountDao.inMoney(in,money);
}
}
我们使用测试类执行
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = SpringConfig.class)
public class AccountServiceTest {
@Autowired
private AccountService accountService;
@Test
public void testTransfer() throws IOException {
accountService.transfer("Tom","Jerry",100D);
}
}
事务同步方法
1,在需要用到spring事务的接口处开启@Transactional
2,在JdbcConfig中配置事务管理器
//配置事务管理器,mybatis使用的是jdbc事务
@Bean
public PlatformTransactionManager transactionManager(DataSource dataSource) {
DataSourceTransactionManager dataSourceTransactionManager = new DataSourceTransactionManager();
dataSourceTransactionManager.setDataSource(dataSource);
return dataSourceTransactionManager;
}
3,由于我们是使用注解形式传入数据源的,所以我们需要在核心配置类里面也开启注解事务驱动 @EnableTransactionManagement
然后执行,发现成功
事务相关配置
由于事务不为IO异常进行处理,所以我们可以亲自进行处理
@Transactional(rollbackFor = {IOException.class})
事务日志记录
当我们对于一个事务无论执行成功与否,都必须要求另一个代码执行的时候(好比转账失败的记录也需要录入数据库)时,我们可以在事务注解处定义新的事务来避免不执行@Transactional(propagation = Propagation.REQUIRES_NEW)