目录
- 前言
- Spring中事务的实现
- 声明式事务
- @Transactional 作⽤范围
- @Transactional 参数说明
- 对于事务不回滚的解决方案
前言
在数据库中我们提到了 事务, 事务的定义为, 将一系列操作封装成一个整体去调用 , 要么一起成功, 要么一起失败
Spring中事务的实现
在Spring中事务的操作分为俩类, 一种是编程式事务(⼿动写代码操作事务) , 而另一种是声明式事务(利⽤注解⾃动开启和提交事务)
其中 编程式事务 , 与SQL中事务的实现有点类似 , 都必须经历三步分别是
开启事务(获取事务)。
提交事务。
回滚事务
SpringBoot 内置了两个对象,DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或回滚事务的,⽽ TransactionDefinition 是事务的属性,在获取事务的时候需要将TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus,实现代码如下
@RestController
public class UserController {@Resourceprivate UserService userService;// JDBC 事务管理器@Resourceprivate DataSourceTransactionManager dataSourceTransactionManager;// 定义事务属性@Resourceprivate TransactionDefinition transactionDefinition;@RequestMapping("/sava")public Object save(User user) {// 开启事务TransactionStatus transactionStatus = dataSourceTransactionManager.getTransaction(transactionDefinition);// 插⼊数据库int result = userService.save(user);// 提交事务dataSourceTransactionManager.commit(transactionStatus);// // 回滚事务// dataSourceTransactionManager.rollback(transactionStatus);return result;}
}
声明式事务
手动编程事务过于繁琐 ,而声明式事务非常简单 ,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务,具体实现代码如下
@RequestMapping("/save")
@Transactional
public Object save(User user) {int result = userService.save(user);return result;
}
@Transactional 作⽤范围
@Transactional 可以⽤来修饰⽅法或类:
修饰⽅法时:需要注意只能应⽤到 public ⽅法上,否则不⽣效。
修饰类时:表明该注解对该类中所有的 public ⽅法都⽣效
@Transactional 参数说明
大多数的在使用事务的情况是,都是默认参数
注意; @Transactional 在异常被捕获的情况下,不会进⾏事务⾃动回滚,它会认为你自己处理调了该异常, 所以你认为它会自动回滚, 但是不会,所以如果在插入数据时, 发生异常, 然后异常被自己定义的try catch 捕获 ,如果异常发生在数据执行之后, 那么数据还会插入到数据库中
@RestController
public class UserController {@Resourceprivate UserService userService;@RequestMapping("/save")@Transactionalpublic Object save(User user) {// 插⼊数据库int result = userService.save(user);try {// 执⾏了异常代码(0不能做除数)int i = 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());}return result;}
}
对于事务不回滚的解决方案
- 继续将异常抛出 - 让Spring 感知到异常的发生
@RequestMapping("/save")
@Transactional(isolation = Isolation.SERIALIZABLE)
public Object save(User user) {// 插⼊数据库int result = userService.save(user);try {// 执⾏了异常代码(0不能做除数)int i = 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());// 将异常重新抛出去throw e;}return result;
}
- 通过手动抛出异常,让程序回滚 , 使用TransactionAspectSupport.currentTransactionStatus() 可
以得到当前的事务,然后设置回滚⽅法 setRollbackOnly 就可以实现回滚了,具体实现代码如下
@RequestMapping("/save")
@Transactional(isolation = Isolation.SERIALIZABLE)
public Object save(User user) {// 插⼊数据库int result = userService.save(user);try {// 执⾏了异常代码(0不能做除数)int i = 10 / 0;} catch (Exception e) {System.out.println(e.getMessage());// ⼿动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return result;
}