Java响应式编程疑问:为何第二种R2DBC保存逻辑无法写入数据库?
问题分析:第二种写法无法保存数据的原因
1. 冷流未被订阅,导致save操作从未执行
Mono属于冷流:只有当存在订阅者(调用subscribe())时,流内部的逻辑才会被触发执行。
在第二个代码中,你在monoItemFromDB.subscribe()的回调里定义了itemMono.flatMap(...)这个流,但这个流没有被任何订阅者订阅——它只是一段“待执行的逻辑描述”,并没有实际被触发,所以里面的itemRepo.save(item)根本不会运行。
对比第一个代码:itemRepo.save(item)是flatMap的返回值,最终会被上层的订阅(比如控制器层的订阅)触发执行,所以能正常保存数据。
2. 手动嵌套订阅违背响应式编程原则
响应式编程的核心是用操作符组合流,而不是手动嵌套subscribe()。手动订阅会:
- 打破流的上下文,无法正确处理背压、错误传播;
- 导致流的执行时机不可控,出现“定义了逻辑但不执行”的情况;
- 代码可读性、可维护性大幅下降。
正确的写法示例
应该用操作符(比如zipWith、flatMap)组合两个Mono,让它们的执行被统一的订阅驱动:
public Mono<Item> modifyItem(Mono<Item> itemMono, int id ) { Mono<Item> monoItemFromDB = itemRepo.findById(id); // 组合两个Mono,等待两者都产生数据后处理 return monoItemFromDB.zipWith(itemMono, (dbItem, item) -> { item.setId(dbItem.getId()); return item; }).flatMap(itemRepo::save); }
内容的提问来源于stack exchange,提问作者Ram
相关产品推荐
相关产品推荐

