事务主要有三种操作:
Spring 中的事务操作分为两类:
SpringBoot 内置了两个对象,
DataSourceTransactionManager ⽤来获取事务(开启事务)、提交或 回滚事务的,
⽽ TransactionDefinition 是事务的属性,在获取事务的时候需要将 TransactionDefinition 传递进去从⽽获得⼀个事务 TransactionStatus,实现代码如下:
@Autowired
DataSourceTransactionManager transactionManager;
@Autowired
TransactionDefinition definition;
@RequestMapping("/blogSubmit")
public String blogSubmit(String title, String content,@SessionAttribute(value = "user",required = false) User user) {
//通过TransactionDefinition属性来获取TransactionStatus对象
TransactionStatus transactionStatus=transactionManager.getTransaction(definition);
Blog blog=new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setUserid(user.getUserId());
blog.setCategory("未定");
blogService.insert(blog);
// transactionManager.commit(transactionStatus);
transactionManager.rollback(transactionStatus);
return "redirect:/Blog_List.html";
}
}
声明式事务的实现很简单,只需要在需要的⽅法上添加 @Transactional 注解就可以实现了,⽆需⼿动 开启事务和提交事务,进⼊⽅法时⾃动开启事务,⽅法执⾏完会⾃动提交事务,如果中途发⽣了没有处理的异常会⾃动回滚事务,具体实现代码如下:
@RequestMapping("/blogSubmit")
@Transactional
public String blogSubmit(String title, String content,@SessionAttribute(value = "user",required = false) User user) {
Blog blog=new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setUserid(user.getUserId());
blog.setCategory("未定");
blogService.insert(blog);
return "redirect:/Blog_List.html";
}
当使用@Transactional修饰类的时候,如果执行的时候没有任何问题,就会自动的正常提交,如果执行的时候程序出现了异常,那么就会自动发生回滚.
@RequestMapping("/blogSubmit")
@Transactional
public String blogSubmit(String title, String content,@SessionAttribute(value = "user",required = false) User user) {
Blog blog=new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setUserid(user.getUserId());
blog.setCategory("未定");
blogService.insert(blog);
int a=10/0;
return "redirect:/Blog_List.html";
}
对于这种问题,程序的代码中出现了异常,所以这个插入博客的这个事务不会正常执行
所以,使用@transaction注解是非常的好用的,对于正常的没有错误的事务,正常提交;对于出现异常的事务,自动回滚.
同时,@transaction还提供了许多不同功能的参数:
value和transactionManager
当有多个事务管理器的时候,我们可以使用该属性来选择哪一个事务管理器
可以规定事务的传播机制,默认是Propagation.REQUIRED
isolation
事务的隔离级别,默认是Isolation.DEFAULT
Spring中事务的隔离级别一共有以下五种:
public enum Isolation {
DEFAULT(-1),
READ_UNCOMMITTED(1),
READ_COMMITTED(2),
REPEATABLE_READ(4),
SERIALIZABLE(8);
}
1. default 默认级别 指Spring的级别和对应的数据库种的级别一致
2. read uncommit 读不提交
3. read commit 读提交
4. repeatable commit 可重复读
5. Serialization 串行化
@Transactional(isolation = Isolation.DEFAULT)
@Transactional(timeout = 1)
这样可以避免加锁解锁的时间消耗
rollbackFor和rollbackForClassName
抛出异常的类型,回滚事务
noRollbackFor和noRollbackForClassName
抛出异常的类型,不回滚事务
但是这个@Transaction注解还有一个例外,那就是被捕获的异常不会回滚,因为它任务这个异常已经被解决掉了,所以不需要回滚了,是安全的
@RequestMapping("/blogSubmit")
@Transactional
public String blogSubmit(String title, String content,@SessionAttribute(value = "user",required = false) User user) {
Blog blog=new Blog();
blog.setTitle(title);
blog.setContent(content);
blog.setUserid(user.getUserId());
blog.setCategory("未定");
blogService.insert(blog);
try {
int a=10/0;
}catch (Exception e){
}
return "redirect:/Blog_List.html";
}
对异常进行try catch之后,就不会回滚了
如何让被捕获的异常也回滚呢?有以下两种方法:
try {
int a=10/0;
}catch (Exception e){
throw e;
}
try {
int a=10/0;
}catch (Exception e){
TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
}
@Transactional 是基于 AOP 实现的,AOP ⼜是使⽤动态代理实现的。如果⽬标对象实现了接⼝, @Transactional 在开始执⾏业务之前,通过代理先开启事务,在执⾏成功之后再提交事务。如果中途遇 到的异常,则回滚事务。
Spring 事务传播机制定义了多个包含了事务的⽅法,相互调⽤时,事务是如何在这些⽅法间进⾏传递 的。
事务传播机制和事务隔离机制的区别是什么?
事务隔离级别是保证多个并发事务执⾏的可控性的(稳定性的),
⽽事务传播机制是保证⼀个事务在多个调⽤⽅法间的可控性的(稳定性的)。
Spring 事务传播机制包含以下 7 种:

下面以一个例子来观察再不同的传播机制下,事务之间的影响是什么样子的.
以下代码实现中,先开启事务先成功插⼊⼀条⽤户数据,然后再执⾏⽇志报错,⽽在⽇志报错是发⽣了 异常:
UserController:
@RestController
public class UserController {
@Resource
private UserService userService;
@Resource
private LogService logService;
@RequestMapping("/save")
@Transactional(propagation = Propagation.REQUIRED)
public Boolean save(User user) {
userService.save(user);
logService.saveLog("⽤户插⼊:" + user.getName());
return true;
}
}
UserService:
@Service
public class UserService {
@Resource
private UserMapper userMapper;
@Transactional(propagation = Propagation.REQUIRED)
public int save(User user) {
System.out.println("执⾏ save ⽅法.");
return userMapper.save(user);
}
}
logService:
@Service
public class LogService {
@Resource
private LogMapper LogMapper;
@Transactional(propagation = Propagation.REQUIRED)
public int save(Log log) {
System.out.println("执⾏ save ⽅法.");
return LogMapper.save(log);
}
}