在MySql中,我们就已经学习过事务了,想必对于事务的大致意思已经是很明确了,但是,在Spring中事务又是指的是什么呢??感兴趣的各位铁汁,请跟着小编的思路来看一下本文相关内容吧!
Spring中的事务操作分为两类:
- 编程式事务(手动写代码操作事务)《——》了解即可(操作繁琐)
- 声明式事务(利用注解,自动开启和提交事务)
前提提示:事务:将一组操作封装成一个执行单元(封装到一起)要么全部成功,要么全部失败!
创建Spring项目的时候,若与MySql相关,请选择框架:
- lombok
- Spring Boot Devtools
- Spring Web
- MyBatis Framework
- MySQL Driver
Spring 声明式事务(自动):
声明式事务的实现很简单,只需要在需要的方法上添加@Transactional注解就可以实现了,无需手动开启事务和提交事务,进入方法时自动开始事务,方法执行完会自动提交事务(没有出现异常情况),如果中途发生了没有处理的异常会自动回滚事务。
那么,请看小编的下述代码:
@RestController
@RequestMapping("/user2")
public class UserController2 {@Autowiredprivate UserServerice userServerice;@RequestMapping("/del")@Transactional//设置事务的各类级别 @Transactional(isolation = Isolation.DEFAULT)public int del(Integer id){if (id==null || id <= 0){return 0;}return userServerice.del(id);}
}
// @Transactional在方法开始之前开启事务,方法正常执行接收之后,提交事务,如果执行途中发生异常,则回滚事务
@Transactional在方法开始之前开启事务,方法正常执行接收之后,提交事务,如果执行途中发生异常,则回滚事务
接下来,在本文中,我们将会接触到另一个方法:Test(测试)

小编一开始是录了视频,但是在本文中传输不过来(懒),然后就手动搞了个操作步骤!!嘿嘿
通过上述步骤,我们便生成了Test测试类,那么,便可以进行下一步操作了!
class UserController2Test {@Transactionpublic int del(Integer id){if (id==null || id <=0){return 0;}int result=userService.del(id);//先删除System.out.println("删除"+result);int num=10/0;//异常,且没有处理return result;}
}
扩展:
@Transactional注解与@Transaction注解@Transactional注解的作用范围:
@Transactional可以用来修饰方法或类- 修饰方法时:需要注意,只能应用到public方法上,否则不生效(推荐此用法)
- 修饰类时:表明该注解对该类中所有的public方法都生效
@Transaction参数说明
value 当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器 TransactionManager当配置了多个事务管理器时,可以使用该属性指定选择哪个事务管理器 propagation 事务的传播行为,默认Propagation.REQUIRED isolation 事务的隔离级别,默认Isolation.DEFAULT timeout 事务的起始时间,默认为-1,如果超过该时间限制,但事务还没有完成,则回滚事务 readOnly 指定事务是否为只读事务,默认为false,为列忽略哪些不需要事务的方法 rollbackFor 用于指定能够触发事务,回滚的异常类型,可以指定多个异常类型 rollbackForClassName 用于指定能够触发事务,回滚的异常类型,可以指定多个异常类型 noRollbackFor 抛出指定的异常类型,不回滚事务,也可以指定多个异常类型
noRollbackForClassName
抛出指定的异常类型,不回滚事务,也可以指定多个异常类型
Spring事务隔离级别:
| DEFAULT | 以连接的数据库隔离级别为准 | 脏读 | 不可重复读 | 幻读 |
| READ_UNCOMMITTED | 读未提交 | 可 | 可 | 可 |
| READ_COMMITTED | 读已提交 | 不可 | 可 | 可 |
| REPEATABLE | 可重复读 | 不可 | 不可 | 可 |
| SERIALIZABLE | 串行化 | 不可 | 不可 | 不可 |
事务隔离级别设定:
@Transactional(isolation = Isolation.DEFAULT)设置事务隔离级别,在进行多线程并发访问的时候,会有隔离上的区别(发生在并发环境中的问题)
事务类型:
- 普通事务
- 只读事务:没有设置事务隔离级别的时候走可重复读(相比于无事务更可控——》可以自定义事务隔离级别)
- 无事务:(默认的隔离级别:可重复读——》不可自定义事务隔离级别)
声明式事务发生异常,并添加try-catch有可能出现异常,事务不会回滚,那么,就会导致业务执行出错。
@Transactional@RequestMapping("/del")public int del(Integer id){if (id==null || id <=0){return 0;}int result=userService.del(id);//先删除System.out.println("删除"+result);//不会回滚try { //有异常,但被捕获,此时非常危险int num=10/0;//异常}catch (Exception e){e.printStackTrace();//仅打印异常,不进行其他操作}return result;return 0;}
解决方法:
1.将异常抛出去,让框架感知到异常,如果框架感知到异常之后,它会自动回滚事务
try { int num=10/0;}catch (Exception e){e.printStackTrace();}
//将异常抛出,让框架去处理
2.通过代码的方式手动回滚事务(企业中常见)
try {int num=10/0;}catch (Exception e){//异常处理:如:记录错误,提示报警信息…………//手动回滚事务TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); //手动回滚事务//Transaction事务//Aspect切面//Support支持对象//currentTransactionStatus当前事务状态码//setRollbackOnly回滚}
经典面试题:Spring事务失效的场景有哪些??
- 非public修饰的方法
- timeout超时
- 代码中有try-catch《——》异常未处理
- 调用类内容使用@Transactional方法
A方法调用B方法,但B方法虽然用public修饰,但由于使用了@Transaction导致事务失效(A方法未使用)
- 数据库不支持事务
@Transaction工作原理:
@Transaction是基于AOP实现的,AOP又是动态代理实现的,如果目标对象实现了接口,默认情况下会采用JDK的动态代理,如果目标对象没有实现接口,会采用CGLIB动态代理,@Transaction在开始执行业务之前,通过代理先开启事务,在执行成功之后在提交事务,如果中途遇到了异常,则回滚事务。
