当前位置: 首页 > news >正文

对Spring的每种事务传播级别的应用场景和失效场景

好的,下面针对Spring的每种事务传播级别,详细说明其应用场景失效场景,帮助更好地理解它们的实际使用。


1. REQUIRED(默认)

  • 应用场景
    • 大多数业务方法,尤其是需要事务支持的操作。
    • 例如:订单创建(主业务)和订单明细插入(子业务)需要在同一个事务中完成。
  • 失效场景
    • 如果外部方法没有事务,内部方法也不会开启事务(取决于外部调用)。
    • 如果外部方法抛出异常,整个事务会回滚,可能导致内部方法的数据操作失效。

2. REQUIRES_NEW

  • 应用场景
    • 需要独立事务的操作,不受外部事务影响。
    • 例如:日志记录、审计操作,即使主业务失败,日志仍需记录。
  • 失效场景
    • 如果外部事务已经存在,内部方法会挂起外部事务,可能导致外部事务的锁等待或死锁。
    • 如果内部方法抛出异常,外部事务不会回滚,但内部事务会回滚。

3. SUPPORTS

  • 应用场景
    • 查询操作,不需要强制事务支持。
    • 例如:读取数据,如果有事务则加入,没有则以非事务方式执行。
  • 失效场景
    • 如果外部方法没有事务,内部方法也不会开启事务,可能导致数据不一致。
    • 不适用于写操作,因为缺乏事务支持可能导致数据丢失。

4. NOT_SUPPORTED

  • 应用场景
    • 不需要事务支持的操作,尤其是与事务冲突的操作。
    • 例如:调用外部系统接口,或者执行一些不需要事务的批量处理。
  • 失效场景
    • 如果外部方法有事务,内部方法会挂起外部事务,可能导致外部事务的锁等待或超时。
    • 不适用于需要事务支持的写操作。

5. MANDATORY

  • 应用场景
    • 强制要求必须在事务中执行的操作。
    • 例如:某些核心业务方法,必须由其他事务方法调用。
  • 失效场景
    • 如果外部方法没有事务,内部方法会抛出异常。
    • 不适用于非事务调用的场景。

6. NEVER

  • 应用场景
    • 强制要求不能在事务中执行的操作。
    • 例如:某些只读操作,或者与事务冲突的操作。
  • 失效场景
    • 如果外部方法有事务,内部方法会抛出异常。
    • 不适用于需要事务支持的写操作。

7. NESTED

  • 应用场景
    • 需要部分回滚的复杂业务逻辑。
    • 例如:订单创建(主事务)和库存扣减(嵌套事务),如果库存扣减失败,只回滚库存操作,不影响订单创建。
  • 失效场景
    • 如果数据库不支持保存点(Savepoint),则无法使用嵌套事务。
    • 如果外部事务回滚,嵌套事务也会回滚。

总结对比表

传播级别应用场景失效场景
REQUIRED大多数业务方法,需要事务支持外部无事务时,内部方法也无事务
REQUIRES_NEW需要独立事务的操作(如日志记录)可能导致外部事务锁等待或死锁
SUPPORTS查询操作,不需要强制事务支持外部无事务时,内部方法也无事务
NOT_SUPPORTED不需要事务支持的操作(如外部调用)挂起外部事务,可能导致锁等待或超时
MANDATORY强制要求必须在事务中执行的操作外部无事务时,抛出异常
NEVER强制要求不能在事务中执行的操作外部有事务时,抛出异常
NESTED需要部分回滚的复杂业务逻辑数据库不支持保存点时无法使用

实际开发建议

  1. 默认使用REQUIRED:适用于大多数业务场景。
  2. REQUIRES_NEW用于独立操作:如日志记录、审计等。
  3. NESTED用于复杂业务:需要部分回滚时使用。
  4. 避免滥用NOT_SUPPORTED和NEVER:除非明确不需要事务支持。
  5. MANDATORY用于强制事务:确保方法必须在事务中调用。

好的,下面通过代码示例展示每种事务传播级别的失效场景,帮助你更直观地理解它们的行为。


1. REQUIRED(默认)

失效场景:外部方法没有事务,内部方法也不会开启事务。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    // 外部方法没有事务
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 内部方法也不会开启事务
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
        throw new RuntimeException("Inner method failed");
    }
}
  • 结果innerMethod抛出异常,但由于外部方法没有事务,数据不会被回滚。

2. REQUIRES_NEW

失效场景:外部事务被挂起,可能导致锁等待或死锁。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 开启新事务,挂起外部事务
    }

    @Transactional(propagation = Propagation.REQUIRES_NEW)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
        throw new RuntimeException("Inner method failed");
    }
}
  • 结果innerMethod抛出异常,内部事务回滚,但外部事务不受影响。如果innerMethod持有锁,可能导致外部事务锁等待。

3. SUPPORTS

失效场景:外部方法没有事务,内部方法以非事务方式执行。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    // 外部方法没有事务
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 以非事务方式执行
    }

    @Transactional(propagation = Propagation.SUPPORTS)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
        throw new RuntimeException("Inner method failed");
    }
}
  • 结果innerMethod抛出异常,但由于没有事务,数据不会被回滚。

4. NOT_SUPPORTED

失效场景:挂起外部事务,可能导致锁等待或超时。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 挂起外部事务,以非事务方式执行
    }

    @Transactional(propagation = Propagation.NOT_SUPPORTED)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
        throw new RuntimeException("Inner method failed");
    }
}
  • 结果innerMethod抛出异常,内部操作不会被回滚,外部事务继续执行。如果innerMethod执行时间过长,可能导致外部事务锁等待。

5. MANDATORY

失效场景:外部方法没有事务,内部方法抛出异常。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    // 外部方法没有事务
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 抛出异常
    }

    @Transactional(propagation = Propagation.MANDATORY)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
    }
}
  • 结果innerMethod抛出IllegalTransactionStateException,因为外部方法没有事务。

6. NEVER

失效场景:外部方法有事务,内部方法抛出异常。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 抛出异常
    }

    @Transactional(propagation = Propagation.NEVER)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
    }
}
  • 结果innerMethod抛出IllegalTransactionStateException,因为外部方法有事务。

7. NESTED

失效场景:数据库不支持保存点,嵌套事务无法使用。
@Service
public class MyService {

    @Autowired
    private MyRepository myRepository;

    @Transactional(propagation = Propagation.REQUIRED)
    public void outerMethod() {
        myRepository.save(new MyEntity("Outer"));
        innerMethod(); // 嵌套事务
    }

    @Transactional(propagation = Propagation.NESTED)
    public void innerMethod() {
        myRepository.save(new MyEntity("Inner"));
        throw new RuntimeException("Inner method failed");
    }
}
  • 结果:如果数据库不支持保存点,innerMethod会回滚,同时外部事务也会回滚。

总结

通过以上代码示例,可以清晰地看到每种事务传播级别的失效场景:

  1. REQUIRED:外部无事务时,内部方法也无事务。
  2. REQUIRES_NEW:外部事务被挂起,可能导致锁等待。
  3. SUPPORTS:外部无事务时,内部方法以非事务方式执行。
  4. NOT_SUPPORTED:挂起外部事务,可能导致锁等待。
  5. MANDATORY:外部无事务时,抛出异常。
  6. NEVER:外部有事务时,抛出异常。
  7. NESTED:数据库不支持保存点时,无法使用。

希望这些代码示例对你有帮助!

相关文章:

  • 20250315在windows10下开热点步骤
  • linux系统CentOS 7版本搭建NFS共享存储
  • 为什么HashMap 头插法会造成死锁
  • JDBC 核心 API 全面解析与高效数据库操作
  • 如何用正则表达式爬取古诗文网中的数据(python爬虫)
  • K8S下nodelocaldns crash问题导致域名请求响应缓慢
  • 基于Python+Flask+MySQL+HTML的爬取豆瓣电影top-250数据并进行可视化的数据可视化平台
  • 睡不着运动锻炼贴士
  • 工程化与框架系列(34)--前端重构技巧指南
  • Compose 实践与探索九 —— DrawModifier 解析
  • Next.js项目MindAI教程 - 第八章:数据统计与可视化
  • CVPR-2025 | 长程视觉语言导航平台与数据集:迈向复杂环境中的智能机器人
  • 论文阅读笔记:Deep Unsupervised Learning using Nonequilibrium Thermodynamics
  • Springboot+mabatis增删改查,设置不可重复字段
  • 基于python+django+vue.js开发的停车管理系统运行-期末作业
  • 嵌入式web服务器实现上传下载储存研究
  • 基于ensp的IP企业网络规划
  • 1191:流感传染--BFS
  • 星越L_三角指示牌及危险警示灯使用
  • 【技术支持】记一次mac电脑换行符差异问题
  • 韧性十足的中国外贸企业:“不倒翁”被摁下去,还会再弹起来
  • 上海高院与上海妇联签协议,建立反家暴常态化联动协作机制
  • 远洋集团:今年前4个月销售80.9亿元,同比增加13.62%
  • 党建评:对违规宴饮等问题要坚决露头就打
  • 马上评|“衣服越来越难买”,对市场是一个提醒
  • 山西临汾哪吒主题景区回应雕塑被指抄袭:造型由第三方公司设计