IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> Java知识库 -> 【Spring事务】事务和事务传播机制 -> 正文阅读

[Java知识库]【Spring事务】事务和事务传播机制

事务

事务主要有三种操作:

  1. 开始事务 start transaction
  2. 提交事务 commit
  3. 回滚事务 rollback

Spring 中事务的实现

Spring 中的事务操作分为两类:

  1. ?动操作事务。
  2. 声明式?动提交事务.

1.?动操作事务

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";  
    }  
}

2. Spring 声明式事务(?动事务)

声明式事务的实现很简单,只需要在需要的?法上添加 @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还提供了许多不同功能的参数:

  1. value和transactionManager
    当有多个事务管理器的时候,我们可以使用该属性来选择哪一个事务管理器

  2. propagation

    可以规定事务的传播机制,默认是Propagation.REQUIRED

  3. 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)
  1. timeout 设置隔离时间,如果超出时间的话,就回滚,默认是-1
@Transactional(timeout = 1)
  1. readOnly 指定事务是只读的,默认值是false,如果开启为true,表示这个事务只允许读,不可以修改.

这样可以避免加锁解锁的时间消耗

  1. rollbackFor和rollbackForClassName

    抛出异常的类型,回滚事务

  2. 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之后,就不会回滚了

如何让被捕获的异常也回滚呢?有以下两种方法:

  1. 再throw出去
try {  
    int a=10/0;  
}catch (Exception e){  
    throw e;  
}
  1. 使用TransactionAspectSupport.currentTransactionStatus().setRollbackOnly()函数
try {  
    int a=10/0;  
}catch (Exception e){  
    TransactionAspectSupport.currentTransactionStatus().setRollbackOnly();  
}

@Transaction的原理

@Transactional 是基于 AOP 实现的,AOP ?是使?动态代理实现的。如果?标对象实现了接?, @Transactional 在开始执?业务之前,通过代理先开启事务,在执?成功之后再提交事务。如果中途遇 到的异常,则回滚事务。

Spring的事务传播机制

Spring 事务传播机制定义了多个包含了事务的?法,相互调?时,事务是如何在这些?法间进?传递 的。

事务传播机制和事务隔离机制的区别是什么?

事务隔离级别是保证多个并发事务执?的可控性的(稳定性的),
?事务传播机制是保证?个事务在多个调??法间的可控性的(稳定性的)。

种类

Spring 事务传播机制包含以下 7 种:

  1. Propagation.REQUIRED:默认的事务传播级别,它表示如果当前存在事务,则加?该事务;如果当前没有事务,则创建?个新的事务
  2. Propagation.SUPPORTS:如果当前存在事务,则加?该事务;如果当前没有事务,则以?事务的 ?式继续运?。
  3. Propagation.MANDATORY:(mandatory:强制性)如果当前存在事务,则加?该事务;如果当 前没有事务,则抛出异常。
  4. Propagation.REQUIRES_NEW:表示创建?个新的事务,如果当前存在事务,则把当前事务挂 起。也就是说不管外部?法是否开启事务,Propagation.REQUIRES_NEW 修饰的内部?法会新开 启??的事务,且开启的事务相互独?,互不?扰。
  5. Propagation.NOT_SUPPORTED:以?事务?式运?,如果当前存在事务,则把当前事务挂起。
  6. Propagation.NEVER:以?事务?式运?,如果当前存在事务,则抛出异常。
  7. Propagation.NESTED:如果当前存在事务,则创建?个事务作为当前事务的嵌套事务来运?;如果当前没有事务,则该取值等价于 PROPAGATION_REQUIRED

在这里插入图片描述

具体演示

下面以一个例子来观察再不同的传播机制下,事务之间的影响是什么样子的.

以下代码实现中,先开启事务先成功插??条?户数据,然后再执??志报错,?在?志报错是发?了 异常:

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);   
    }
}
  1. 当传播机制的类型是REQUIRED的时候,表示后来的事务都加入原来的事务.所以,当日志发送异常回滚之后,因为它们已经成一体了,所以用户插入也会失败,也会回滚
  2. 当传播机制的类型是REQUIRED_NEW的时候,因为这个不使用当前事务,而是新创建一个事务,所以日志事务和用户事务都是相互独立的.日志事务发生回滚不会影响用户事务的正常提交
  3. 当传播机制的类型是NESTY的时候,也就是嵌套机制时,当日志发送错误的时候,也只是回滚日志,用户事务正常执行.这是因为嵌套机制在嵌套的时候会有一个连接点,每次回滚之后都会回到相应的连接点,不会全部回滚
  4. 当传播机制的类型是NOT_SUPPORTED的时候,也就是不支持事务的类型.就算是日志出现了异常,但是因为不是以事务的机制运行的,所以就会正常的提交,不会发生回滚
  Java知识库 最新文章
计算距离春节还有多长时间
系统开发系列 之WebService(spring框架+ma
springBoot+Cache(自定义有效时间配置)
SpringBoot整合mybatis实现增删改查、分页查
spring教程
SpringBoot+Vue实现美食交流网站的设计与实
虚拟机内存结构以及虚拟机中销毁和新建对象
SpringMVC---原理
小李同学: Java如何按多个字段分组
打印票据--java
上一篇文章      下一篇文章      查看所有文章
加:2022-09-15 01:51:23  更:2022-09-15 01:54:20 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/23 13:06:13-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码