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日

相关文章

  • 2023年4月21日-关于远程feign调用实现文件上传下载

    一、客户需求:做一个查询程序,客户提供一个excel模板,将查询结果保存到excel模板中,上传到文件服务,供客户下载使用。 二、代码实现 // 服务A,文件上传 @ApiOperation(“上传文件-demo”) @PostMapping(value = “/uploadDemo/{busType}/{billId}”) public ResBean u…

    Java 2023年4月22日
    00
  • boot-admin开源项目中有关后端参数校验的最佳实践

    我们在项目开发中,经常会对一些参数进行校验,比如非空校验、长度校验,以及定制的业务校验规则等,如果使用if/else语句来对请求的每一个参数一一校验,就会出现大量与业务逻辑无关的代码,繁重不堪且繁琐的校验,会大大降低我们的工作效率,而且准确性也无法保证。为保证数据的正确性、完整性,前后端都需要进行数据检验。本文对开源 boot-admin 项目的后端校验实践…

    Java 2023年5月7日
    00
  • java中List对象排序通用方法

    请允许我详细讲解一下“Java中List对象排序通用方法”的完整攻略。 一、List对象排序的基本思路 在Java中,List是一种常见的集合类型,可以用来存储一组数据。在实际开发过程中,我们会遇到需要对List中的数据进行排序的需求。通用的 List 对象排序方法需要以下步骤: 对于自定义对象,需要实现 Comparable 接口或者传入一个 Compar…

    Java 2023年5月26日
    00
  • ASP.NET 页面刷新的实现方法(包括html,js)

    ASP.NET 页面刷新的实现方法可以通过 HTML 页面自身的 meta 标记或者使用 JavaScript 来完成。 通过 HTML 页面的 meta 标记实现页面刷新 HTML 页面可以通过设置 meta 标记来控制页面的刷新,具体方法为: <!–每5秒自动刷新页面–> <meta http-equiv="refresh…

    Java 2023年6月15日
    00
  • 对象头包括哪些内容?

    以下是关于“对象头包括哪些内容?”的完整使用攻略: 1. 对象头的结构 在Java中,每个对象都有一个对象头,用于存储对象的元数据信息。对象头包含了以下几个部分: Mark Word:用于存储对象的哈希码、锁状态、GC信息等。 Class Pointer:指向对象的类元数据信息。 Array Length:仅在数组对象中存在,用于存储数组的长度。 对象头的大…

    Java 2023年5月12日
    00
  • JavaWeb实战之开发网上购物系统(超详细)

    JavaWeb实战之开发网上购物系统(超详细) 完整攻略 系统需求 为了方便读者更好地理解开发过程,我们假设我们要开发一个网上购物系统,该系统需要满足以下基本需求: 用户可以浏览商品信息,并将商品添加进购物车。 用户可以查看购物车中的商品,并对购物车中的商品进行结算。 用户可以对订单进行在线支付。 管理员可以管理商品信息,包括添加商品、删除商品、修改商品信息…

    Java 2023年5月24日
    00
  • JAVA读取文件流,设置浏览器下载或直接预览操作

    让我来详细讲解如何使用Java读取文件流并设置浏览器下载或直接预览操作。 1. 读取文件流 Java读取文件流可以使用java.io包中的FileInputStream类。该类提供了多种读取文件流的方式。 示例1:直接读取文件流 import java.io.File; import java.io.FileInputStream; import java.…

    Java 2023年5月19日
    00
  • Springmvc ResponseBody响应json数据实现过程

    为了实现Spring MVC ResponseBody响应JSON数据,我们需要使用Jackson来序列化Java对象到JSON格式的字符串,然后将其添加到HTTP响应中。以下是实现此过程的完整攻略: 准备工作 在开始进行Spring MVC ResponseBody响应JSON数据的实现过程之前,我们需要执行以下步骤: 确保在项目中引入了Jackson库,…

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