同一类内从非Transactional方法调用Transactional方法的潜在运行时问题
同一类中非事务方法调用事务方法的潜在问题分析
首先明确核心原因:Spring事务依赖动态代理实现,同一类内部方法调用时,不会经过代理类,所以@Transactional注解不会生效,事务上下文不会被创建。
你用MongoDB测试时代码能正常运行,是因为当前fetchCourses方法只有单一的读操作——MongoDB的Repository查询本身不需要事务就能执行,而且readOnly=true的事务配置对MongoDB的读操作几乎没有影响,所以不会出现明显问题。但在以下场景中,这种调用方式会引发运行时问题:
- 多操作需要一致性保障时:如果后续给
fetchCourses添加多个读操作(比如先查学生信息,再查关联的课程列表),没有事务的话,两次查询可能拿到不一致的数据(MongoDB默认读隔离级别是读已提交,无法保证不可重复读)。比如在两次查询之间,其他线程修改了学生的课程数据,就会导致前后结果不一致。 - 方法包含写操作时:如果
fetchCourses后续加入写逻辑(比如更新学生的课程权限),没有事务的话,写操作会脱离事务控制。比如先读再写的场景中,中间被其他线程篡改数据,会导致脏写或数据覆盖,无法保证操作的原子性。 - 切换到事务敏感型数据库时:如果换成MySQL等关系型数据库,当
fetchCourses依赖事务特性(比如利用Hibernate一级缓存减少重复查询、需要特定隔离级别保证数据一致性),缺失事务上下文会导致:重复查询数据库、隔离级别不符合预期(比如原本期望的可重复读变成读已提交),甚至在某些依赖事务的操作中抛出异常。 - 使用依赖事务上下文的特性时:如果方法中用到
TransactionSynchronizationManager的相关功能,或者某些需要事务上下文的Spring组件,缺失事务会直接抛出找不到事务上下文的运行时异常。
内容的提问来源于stack exchange,提问作者Gul Ahmed
相关产品推荐
相关产品推荐

