spring的@Transactional注解用法解读

下面是关于“spring的@Transactional注解用法解读”的完整攻略。

什么是@Transactional注解?

@Transactional是Spring框架中用于实现事务管理的注解。在一个被该注解标注的方法或类上使用该注解,可以使得这个方法或类变为一个事务处理的方法或类,在这个方法或类的执行过程中,会同步进行数据源的事务管理。

@Transactional注解的属性

在使用@Transactional注解时,可以指定以下属性来控制事务的管理。

  • propagation:事务的传播行为,默认值为REQUIRED。包括以下传播行为:
  • REQUIRED:表示当前方法必须在事务内执行,如果当前上下文中已经有了事务,当前方法就在这个事务内执行,否则就开启一个新的事务。
  • REQUIRES_NEW:表示当前方法必须在新的事务内执行,如果当前上下文中已经有了事务,就将该事务挂起,当前方法在新的事务内执行。
  • SUPPORTS:表示当前方法支持事务,但可以继承上下文中的事务(如果有)。
  • NOT_SUPPORTED:表示当前方法不支持事务,如果存在事务就将其挂起。
  • MANDATORY:表示当前方法必须在事务内执行,如果当前上下文中没有事务,就抛出异常。
  • NEVER:表示当前方法不能在事务内执行,如果当前上下文中有事务就抛出异常。
  • NESTED:表示当前方法必须在另一个事务内执行,当前方法创建一个新的保存点,并只对这个保存点回滚。

  • isolation:事务的隔离级别,默认值为DEFAULT,包括以下隔离级别:

  • DEFAULT:表示使用底层数据源的默认隔离级别。
  • READ_COMMITTED:表示事务中操作的数据,只要已经提交,就可以被另一个事务读取,可避免脏读现象。
  • READ_UNCOMMITTED:表示无法解决脏读、不可重复读、幻读的问题,不应该在生产环境中使用。
  • REPEATABLE_READ:表示事务中操作的数据,只有在当前事务之前已经被锁定,才能被当前事务访问,可避免脏读和不可重复读现象。
  • SERIALIZABLE:表示所有事务必须依次进行,且不能并发执行。

  • timeout:事务的超时时间,默认值为-1,单位为秒。

  • readOnly:表明事务是否为只读事务,默认值为false。

  • rollbackFor:异常类数组,当出现异常时,事务就会回滚。

  • noRollbackFor:异常类数组,当出现这些异常时,事务不会回滚。

@Transactional在方法上的使用方法

在方法上使用@Transactional注解时,需要在方法声明上加上该注解。例如:

@Transactional
public void saveUser(User user) {
    userDao.save(user);
}

上面的代码中,saveUser方法在执行时,如果之前还没有开启事务,就会自动开启一个事务;如果当前的方法已经在一个开启的事务内,保存操作将会在该事务内完成;如果该方法执行成功,事务就会被提交,如果其中有一个或多个操作失败,则整个事务会被回滚,所有变更将会被撤回。

@Transactional在类上的使用方法

在类上使用@Transactional注解时,该注解会应用到所标注的类中的所有方法中。例如:

@Transactional
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    public void saveUser(User user) {
        userDao.save(user);
    }

    @Override
    public void updateUser(User user) {
        userDao.update(user);
    }
}

上面的代码中,@Transactional注解标注在了类上,是该类中的所有方法都会受到其影响,如果该类中的任意一个方法当中出现了异常,那么在这个事务的生命周期内,所有未提交的更改都将被回滚。

示例1:事务的嵌套

@Transactional
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void saveUser(User user) {
        userDao.save(user);
    }

    @Override
    public void updateUser(User user) {
        userDao.update(user);
        // 保存其它业务数据
        try {
            saveOtherData();
        } catch(Exception e) {
            throw new RuntimeException("保存其它业务数据失败", e);
        }
    }

    // 保存其它业务数据
    private void saveOtherData() {
        // do something
    }
}

上面的代码中,saveUser方法的事务传播行为为REQUIRES_NEW,表示该方法已经开启了一个新的事务;在updateUser方法中调用了saveOtherData方法,该方法会在当前事务中执行,如果保存数据失败了,就会抛出异常。此时,该异常会被抛到updateUser方法中,因为该方法在一个已经开启的事务中执行,整个事务就会被回滚,而saveUser方法开启的事务并不受updateUser方法的回滚影响,依然会在数据源中保存成功。

示例2:基于异常回滚

@Transactional
@Service
public class UserServiceImpl implements UserService {

    @Autowired
    private UserDao userDao;

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public void saveUser(User user) {
        userDao.save(user);
        if (StringUtils.isBlank(user.getNickname())) {
            throw new RuntimeException("昵称不能为空");
        }
    }

    @Override
    public void updateUser(User user) {
        userDao.update(user);
    }
}

上面的代码中,saveUser方法的事务标注了rollbackFor属性,表示只有当该方法抛出RuntimeException时,才会回滚整个方法的所有更改。如果在该方法中执行了若干操作,但其中只有一项出现了问题,其它操作都执行成功了,即使抛出了异常,也只会回滚该方法中失败的操作,而其它成功的操作并不会被回滚。这样就可以避免因为某些无关紧要的操作导致整个事务全部回滚,提高了数据操作的准确性。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:spring的@Transactional注解用法解读 - Python技术站

(0)
上一篇 2023年5月20日
下一篇 2023年5月20日

相关文章

  • 详解Java的JDBC API中事务的提交和回滚

    下面是详解Java的JDBC API中事务的提交和回滚的攻略: 1. 事务基本概念 在数据库操作中,事务是指一系列的数据库操作,这些操作要么全部执行成功,要么全部失败。事务操作具有原子性、一致性、隔离性和持久性四个特征,简称ACID(Atomicity、Consistency、Isolation、Durability)。其中: 原子性:指事务中的所有操作要么…

    Java 2023年5月20日
    00
  • JSP页面中如何用select标签实现级联

    要在JSP页面中使用select标签实现级联,可以遵循以下步骤: 确定级联关系 在使用select标签实现级联前,需要确定级联关系,即第一个下拉框的选择决定了第二个下拉框的选项。例如,第一个下拉框选择区域,第二个下拉框选择该区域的城市。 创建第一个下拉框 使用HTML的select标签创建第一个下拉框,并给每个选项赋值。例如,在第一个下拉框里,我们可以创建几…

    Java 2023年6月15日
    00
  • JSP实现网页访问统计

    JSP(Java Server Pages)是一种动态网页技术,常用于开发企业级Web应用程序。通过使用JSP和Servlet,我们可以轻松地创建具有动态内容的网页,这其中包括网站访问次数统计。 下面是实现JSP实现网页访问统计的完整攻略: 步骤1:创建数据库 为了存储网站访问信息,我们需要先创建一个数据库,并在其中创建一个表格来存储访问信息。 可以使用My…

    Java 2023年6月15日
    00
  • Java深入浅出数组的定义与使用上篇

    我来为你讲解一下“Java深入浅出数组的定义与使用上篇”的完整攻略。 标题 标题应该使用Markdown语法中的“#”,一级标题用“#”表示,二级标题用“##”表示,以此类推。这篇攻略的一级标题可以命名为“Java深入浅出数组的定义与使用上篇”。 正文 在开始正文之前,需要简单介绍一下本文主要讲解的内容。本篇攻略主要分为三个部分,分别是数组的定义、数组的初始…

    Java 2023年5月26日
    00
  • 微信小程序webSocket的使用方法

    接下来我将详细讲解微信小程序中使用WebSocket的方法。主要分为以下几个步骤: 1. 引入WebSocket API 在小程序页面js文件里,需要引入WebSocket API,代码如下: // 引入WebSocket API const socket = require(‘../../utils/websocket.js’) 其中websocket.j…

    Java 2023年5月23日
    00
  • java 输入一个数字组成的数组(输出该数组的最大值和最小值)

    要输入一个数字组成的数组并输出该数组的最大值和最小值,可以按照下列步骤进行操作。 第一步:创建数组 首先,需要创建一个空数组,用于存储输入的数字。 int[] nums = new int[n]; 此代码段将创建一个整数类型的数组,数组长度为n。 第二步:输入数组数据 接下来,需要循环输入n个数字,将这些数字存入数组中。 Scanner scanner = …

    Java 2023年5月26日
    00
  • Struts2实现文件上传功能实例解析

    让我给你详细讲解一下“Struts2实现文件上传功能实例解析”的完整攻略。 1. 导入相关依赖 首先,我们需要在项目的pom.xml文件中导入相关依赖: <dependency> <groupId>commons-fileupload</groupId> <artifactId>commons-fileuplo…

    Java 2023年5月20日
    00
  • Advanced SQL Injection with MySQL

    Advanced SQL Injection with MySQL是一种比较高级的SQL注入攻击方式,需要攻击者对SQL语言和MySQL数据库的运作方式非常熟悉。下面是一个完整的攻击步骤: 1. 了解目标网站的数据库类型和版本 在进行SQL注入攻击之前,我们需要了解目标网站所使用的数据库类型和版本。假设我们已经知道目标网站正在使用MySQL数据库,我们可以尝…

    Java 2023年6月16日
    00
合作推广
合作推广
分享本页
返回顶部