什么是事务:
事务是一组操作的集合,是不可分割的操作。比如一系列sql语句在一个操作中执行,要么成功要么失败。
比如在转账的时候,a钱包-100,b钱包+100,两个要么同时成功要么同时失败。
(复习)mysql事务的操作主要有三步:
- 开启事start transaction/ begin (⼀组操作前开启事务)
- 提交事务: commit (这组操作全部成功, 提交事务)
- 回滚事务: rollback (这组操作中间任何⼀个操作出现异常, 回滚事务)
Spring中的事务:
编程式事务(⼿动写代码操作事务).
在这里我们观察数据库后发现并没有数据插入,是因为我们回滚了,执行了但是回滚了。这里太麻烦了所以一般用声明式事务。
声明式事务(利⽤注解⾃动开启和提交事务)。
package com.syx.springtrans.Controller;import com.syx.springtrans.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/trans")
public class TransController {@AutowiredUserService userService;@Transactional@RequestMapping("/register")public boolean register(String userName,String password){Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);}
}
这里我们通过@Transactional的注解来进行自动事务和回滚,自动提交或者回滚
运行成功自动提交事务,程序失败的时候自动回滚。
package com.syx.springtrans.Controller;import com.syx.springtrans.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/trans")
public class TransController {@AutowiredUserService userService;@Transactional@RequestMapping("/register")public boolean register(String userName,String password){Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);int n=10/0;return true;}
}
在这边我们增加了一个错误10/0这时候后端在前端访问的时候就会报错,事务就会回滚,但是如果我们trycatch住,方法就感知不到发生异常,就不会回滚。
但是如果catch之后仍然希望回滚。
方法1.通过throw方法,将异常扔出去
@Transactional@RequestMapping("/register")public boolean register(String userName,String password){Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);try {int n=10/0;}catch (Exception e){e.printStackTrace();throw e;}return true;}
方法二:TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();
@Transactional@RequestMapping("/register")public boolean register(String userName,String password){Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);try {int n=10/0;}catch (Exception e){TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();}return true;}
通过该方法可以手动回滚。
这是事务回滚时候的日志
这是事务提交时候的日志:多了个committing
package com.syx.springtrans.Controller;import com.syx.springtrans.Service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.transaction.interceptor.TransactionAspectSupport;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import java.io.IOException;@RestController
@RequestMapping("/trans")
public class TransController {@AutowiredUserService userService;@Transactional@RequestMapping("/register")public boolean register(String userName,String password) throws IOException {Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);try {int n=10/0;}catch (Exception e){throw new IOException();}return true;}
}
如果这时候自己抛出一个异常,并且把异常添加在方法的后面,这时候就会发生一个现象,就是提交成功。(不是RuntimeException和error)。
为什么呢?
只有在发生error和RuntimeException事务才会回滚。
@Transactional(rollbackFor = Exception.class)@RequestMapping("/register1")public boolean register1(String userName,String password) throws IOException {Integer integer = userService.insertUserInfo(userName, password);System.out.println("integer的值是"+integer);try {int n=10/0;}catch (Exception e){throw new RuntimeException();}return true;}
可以通过rollbackFor()指定发生什么异常的时候进行回滚。
小总结:默认发生RunTimeException和error的时候才会进行回滚,可以通过RollbackFor指定发生异常进行回滚的对象
事务回滚级别
面试题:
这是spring中的事务隔离级别,设置事务隔离级别,下面四种最重要。