springboot 事务(@Transactional)

@Transactional注解

        在springboot中,在方法或类上添加@Transactional注解,将会把该方法或类中的数据库操作放到一个事务中,中途发生异常时,则事务会回滚,代码如下

    @Transactional
    public void test(){
        //数据库操作1
        //数据库操作2
        //数据库操作3
        //数据库操作4
    }

@Transactional参数如下

参数说明
rollbackFor指定事务回滚的异常类型,可以指定一个或多个异常类型的数组,当方法抛出指定异常或其子类时,事务将回滚。
noRollbackFor指定不触发事务回滚的异常类型。可以设置一个或多个异常类型的数组。当方法中抛出指定的异常或其子类时,事务不会回滚。
timeout指定事务的超时时间,单位为秒,默认值为-1,表示没有超时限制。
readOnly指定事务是否为只读事务,默认值为false。如果设置为true,表示事务只涉及读操作,可以优化事务管理的性能。
isolation指定事务的隔离级别,默认值为Isolation.DEFAULT。可以使用Isolation枚举类中的不同选项来设置隔离级别,如DEFAULT、READ_UNCOMMITTED、READ_COMMITTED等,事务隔离级别请参考数据库事务
Propagation指定事务的传播行为,默认值为Propagation.REQUIRED。可以使用Propagation枚举类中的不同选项来设置传播行为,如REQUIRED、REQUIRES_NEW、SUPPORT

 事务的传播性

  •  REQUIRED:如果当前存在事务,则在该事务中执行方法;如果没有事务,则创建一个新的事务。这是最常用的传播性,方法调用将在同一个事务中执行。
  • REQUIRES_NEW:每次都创建一个新的事务,并挂起当前事务(如果存在)。新事务与外部事务完全独立,方法调用将在新的事务中执行。
  • SUPPORTS:如果当前存在事务,则在该事务中执行方法;如果没有事务,则以非事务的方式执行。方法调用不强制要求在事务中执行。
  • NOT_SUPPORTED:以非事务的方式执行方法。如果当前存在事务,则将其挂起,方法调用不在事务中执行。
  • MANDATORY:要求当前存在事务,并在该事务中执行方法。如果没有事务,则抛出异常。
  • NEVER:禁止在事务中执行方法。如果当前存在事务,则抛出异常。
  • NESTED:如果当前存在事务,则在嵌套事务中执行方法。如果没有事务,则创建一个新的事务。嵌套事务可以独立提交或回滚,但它受外部事务的影响。

事务避坑

  • 自调用方法:如果一个带有事务的方法在同一个类中通过普通的方法调用自己,事务传播可能会失效。这是因为Spring会基于代理机制来管理事务,而自调用方法不会经过代理对象。为了避免这个问题,可以将自调用的方法抽取到另一个类中,并通过依赖注入的方式调用。

  • 异步方法:在异步方法中,默认情况下,事务不会被传播到异步方法中。这是因为异步方法会在新的线程中执行,而事务是与当前线程绑定的。要在异步方法中启用事务传播,可以使用@Async+@Transactional注解来继承父线程的事务上下文

  • 不同的异常处理:事务的回滚通常是基于抛出的异常类型来决定的。如果在事务内部捕获了异常并处理了它,那么事务可能不会回滚,除非在捕获的异常处理中手动抛出一个与事务回滚相关的异常。

  • 多个事务注解:在同一个方法上同时使用多个事务注解(如@Transactional@TransactionAttribute)可能导致事务的行为不可预测。应该避免在同一个方法上使用多个事务注解,以免出现冲突和不一致的事务行为。

  • 外部调用:如果一个有事务的方法被另一个没有事务的方法直接调用,事务传播可能会受到影响。在这种情况下,被调用的方法会在自己的事务中执行,而不是加入到外部方法的事务中。要确保事务传播正常工作,应该通过代理对象来调用有事务的方法。

  • 外部类调用:如果一个有事务的方法被另一个类的方法调用,事务传播可能会受到影响。如果被调用的方法是通过依赖注入的方式注入到外部类中的,那么事务传播应该正常工作。但是,如果被调用的方法是通过直接实例化的方式创建的对象,并且不经过Spring的代理对象,事务传播可能会失效。

异步调用事务传播代码如下:

    @Async
    @Transactional
    public void yourAsyncTransactionalMethod() {
        // 异步事务处理
    }

 外部调用通过代理对象调用有事务的方法代码:

@Service
public class YourService {
    @Transactional
    public void yourTransactionalMethod() {
        // 事务处理
    }
}

public class OuterClass {
    public void outerMethod() {
        YourService targetObject = (YourService) AopProxyUtils.getSingletonTarget(yourService);
        targetObject.yourTransactionalMethod(); // 通过目标对象调用有事务的方法
    }
}

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
@TransactionalSpring框架中用于配置事务的注解之一,它可以被应用于类或方法上。当被应用于类上时,该类中的所有公共方法都将被配置为支持事务。当被应用于方法上时,该方法将被配置为支持事务。@Transactional注解提供了多个属性,可以用于配置事务的各个方面,例如隔离级别、传播行为、只读状态等。以下是一个使用@Transactional注解配置事务的例子: ```java @Service public class UserServiceImpl implements UserService { @Autowired private UserDao userDao; @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false) public void addUser(User user) { userDao.addUser(user); } @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false) public void updateUser(User user) { userDao.updateUser(user); } @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.DEFAULT, readOnly = false) public void deleteUser(int userId) { userDao.deleteUser(userId); } @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.DEFAULT, readOnly = true) public User getUserById(int userId) { return userDao.getUserById(userId); } @Transactional(propagation = Propagation.SUPPORTS, isolation = Isolation.DEFAULT, readOnly = true) public List<User> getAllUsers() { return userDao.getAllUsers(); } } ``` 在上面的例子中,@Transactional注解被应用于UserServiceImpl类中的所有公共方法上。其中,propagation属性指定了事务的传播行为,isolation属性指定了事务的隔离级别,readOnly属性指定了事务是否只读。在这个例子中,事务的传播行为被配置为REQUIRED,表示如果当前没有事务,则创建一个新的事务;如果当前已经存在事务,则加入该事务事务的隔离级别被配置为DEFAULT,表示使用数据库默认的隔离级别。事务的只读状态被配置为false,表示该事务可以读取和修改数据。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值