Spring 事务详解
前言👀~
上一章我们介绍了Spring AOP,今天来讲解Spring事务
什么是事务?
为什么需要事务?
Spring 中事务的实现
1.编程式事务
2.声明式事务
@Transactional详解
1. rollbackFor
2. Isolation
3. propagation
1. REQUIRED(默认值)
2. REQUIRES_NEW
3.NEVER
4.Nested
如果各位对文章的内容感兴趣的话,请点点小赞,关注一手不迷路,讲解的内容我会搭配我的理解用我自己的话去解释如果有什么问题的话,欢迎各位评论纠正 🤞🤞🤞
个人主页:N_0050-CSDN博客
相关专栏:java SE_N_0050的博客-CSDN博客 java数据结构_N_0050的博客-CSDN博客 软件测试_N_0050的博客-CSDN博客 MySQL_N_0050的博客-CSDN博客 java EE_N_0050的博客-CSDN博客
什么是事务?
回顾之前数据库中的事务,事务是一组操作的集合,在数据库中可以把事务看作是一组SQL语句,例如转账这个操作就会涉及到多条SQL语句也就是一组集合,这个操作要么都成功要么都失败,所以事务具有原子性
为什么需要事务?
上面的例子中就说明为什么需要事务了,如果转账过程中转账方扣款成功,但是接收方未收到收款就会出现问题,所以我们使用事务可以解决这个问题,让一组操作要么都成功要么都失败
事务的操作:
1. 开启事务:start transaction/ begin (⼀组操作前开启事务)
2. 提交事务:commit (这组操作全部成功,提交事务)
3. 回滚事务:rollback (这组操作中间任何⼀个操作出现异常,回滚事务)
Spring 中事务的实现
1.编程式事务
类似MySQL事务,手动开启事务,手动提及事务,手动回滚事务。SpringBoot 内置了两个对象:DataSourceTransactionManager 事务管理器,用来获取事务(开启事务),提交或回滚事务。TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus
• 代码演示,先把对应的数据准备好
@Data public class UserInfo { private Integer id; private String userName; private String password; private Date createTime; private Date updateTime; }
@Mapper public interface UserInfoMapper { @Insert("insert into user_info(`user_name`,`password`)values(#{userName},#{password})") Integer insert(@Param("userName") String userName, @Param("password") String password); }
@Service public class UserService { @Autowired private UserInfoMapper userInfoMapper; public Integer insert(String userName, String password) { return userInfoMapper.insert(userName, password); } }
观察输出结果,返回注册成功,观察一下日志也是插入成功返回结果也是1
但是数据库中没有数据!!!说明事务回滚了
我们修改一下代码试试
@Slf4j @RequestMapping("/user") @RestController public class UserInfoController { //事务管理器 @Autowired private DataSourceTransactionManager dataSourceTransactionManager; //事务的属性 @Autowired private TransactionDefinition transactionDefinition; @Autowired private UserService userService; @RequestMapping("/registry") public String registry(String userName, String password) { TransactionStatus transaction = dataSourceTransactionManager.getTransaction(transactionDefinition); Integer result = userService.insert(userName, password); log.info("用户插入成功,result:" + result); dataSourceTransactionManager.commit(transaction); return "注册成功"; } }
观察输出结果,接口返回的还是注册成功,再看看日志这次多了一条语句,提交了sqlSession
观察数据库,id为2,说明上条数据确实有插入但是事务回滚了
2.声明式事务
通过@Transactional注解来实现自动开启和提交事务(推荐),这个注解注意应当加到我们Service里对应的是业务逻辑层。无需手动开启事务和提交事务,进⼊方法时⾃动开启事务,⽅法执行完会自动提交事务,如果中途发生了没有处理的异常会自动回滚事务。如果所在方法没有抛出异常时,事务就提交
@Transactional注解可以用来修饰⽅法或类:
1.修饰⽅法时:只有修饰public ⽅法时才⽣效(修饰其他⽅法时不会报错,也不生效)
2.修饰类时:对 @Transactional 修饰的类中所有的 public ⽅法都生效
• 下面进行演示,正常情况
@Slf4j @RequestMapping("/user") @RestController public class UserInfoController { @Autowired private UserService userService; @Transactional @RequestMapping("/registry") public String registry(String userName, String password) { Integer result = userService.insert(userName, password); log.info("用户插入成功,result:" + result); return "注册成功"; } }