面试题系列:关于@Transactional你了解多少?

狮子也疯狂 元老
全栈领域优质创作者
博客专家认证
2023-07-24 08:43:48

作者平台:

| CSDN:https://blog.csdn.net/qq/_41153943%EF%BC%88ID%EF%BC%9A%E6%B1%9F%E5%A4%8F%E3%80%81

| 掘金:https://juejin.cn/user/651387938290686%EF%BC%88ID%EF%BC%9Ajiangxia/_1024

| 知乎:https://www.zhihu.com/people/1024-paper-96%EF%BC%88ID%EF%BC%9A%E6%B1%9F%E5%A4%8F

| GitHub:https://github.com/JiangXia-1024?tab=repositories

本文一共1278字,预计阅读12分钟

1、介绍

@Transactional 是 Spring 框架中的一个注解,用于标识某个方法或类需要进行事务管理。它的原理是基于 AOP(面向切面编程)和代理模式。

当使用 @Transactional 注解时,Spring 会通过动态代理的方式为被注解的方法生成一个代理对象。这个代理对象会拦截方法的调用,在方法执行前后开启和提交事务。具体原理如下:

1. 在方法调用前,代理对象会开启一个新的事务。如果已经存在一个事务,则会加入该事务中。

2. 方法执行过程中,如果发生异常,则事务会被回滚,即撤销已经执行的操作。

3. 方法执行完成后,代理对象会提交事务。如果事务执行过程中发生异常,事务会被回滚。

@Transactional 注解还有一些属性可以设置,例如 isolation(事务隔离级别)、propagation(事务传播行为)、timeout(事务超时时间)等,可以根据具体需求进行配置。

2、代码

下面是一个简单的代码演示,展示了如何使用 @Transactional 注解进行事务管理:

@Service
public class UserService {
    
    @Autowired
    private UserRepository userRepository;
    
    @Transactional
    public void createUser(User user) {
        userRepository.save(user);
    }
    
    @Transactional(propagation = Propagation.REQUIRED, rollbackFor = Exception.class)
    public void updateUser(User user) {
        userRepository.save(user);
        if (user.getId() == null) {
            throw new IllegalArgumentException("User ID cannot be null");
        }
    }
    
    @Transactional(propagation = Propagation.REQUIRED, timeout = 10)
    public void deleteUser(Long userId) {
        userRepository.deleteById(userId);
    }
}

在上面的示例中,UserService 类中的三个方法都使用了 @Transactional 注解。

- createUser 方法使用了默认的事务传播行为和超时时间,即默认情况下会开启一个新的事务,并且没有设置超时时间。

- updateUser 方法设置了事务传播行为为 REQUIRED(如果当前存在事务,则加入该事务),并且设置了回滚策略为 Exception.class,即遇到任何异常都会触发事务回滚。

- deleteUser 方法设置了事务传播行为为 REQUIRED,超时时间为 10 秒,即如果方法执行时间超过 10 秒,事务会自动回滚。

需要注意的是,在 UserService 类中的方法之间进行调用时,@Transactional 注解可能不会生效。如果想要在调用方法内部也生效,可以将方法抽取到另一个类中,或者使用 self-invocation(通过 this 调用方法)。

希望以上示例能够帮助你理解 @Transactional 注解的使用和原理。

3、@Transactional的坑

使用 @Transactional 注解时需要注意一些坑:

1. 注解的类或方法必须是 public 的,因为 Spring 使用动态代理来生成代理对象,只能代理公共方法。

2. 默认情况下,只有抛出 RuntimeException 及其子类的异常才会触发事务回滚。如果要让其他异常也触发事务回滚,可以使用 @Transactional(rollbackFor = Exception.class) 来设置。

3. 在同一个类中的方法调用,@Transactional 注解可能不起作用。这是因为 Spring 使用的是基于代理的 AOP,默认只能拦截从外部调用的方法。可以通过将方法抽取到另一个类中,或者使用 self-invocation(通过 this 调用方法)来解决这个问题。

4. @Transactional 注解应该被应用到 public 方法上,而不是 private 或 protected 方法上。因为 Spring 使用的是基于代理的 AOP,只能拦截公共方法。

4、总结

总之,@Transactional 注解可以方便地实现事务管理,但在使用时需要注意一些细节,避免出现意外的问题。

最后感谢大家的关注!

-END-

...全文
139 回复 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
回复
切换为时间正序
请发表友善的回复…
发表回复

118

社区成员

发帖
与我相关
我的任务
社区描述
csdn新星计划top3 | csdn全栈新星创作者 | 阿里云博客专家 | 喜欢编程,主攻Java后端方向 | 希望在csdn能和你共同进步
java-zookeeperjava-rabbitmqspring boot 个人社区 广东省·广州市
社区管理员
  • 狮子也疯狂
  • 码银
  • bluetata
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧