You need to enable JavaScript to run this app. 如何在Spring Reactive应用中检查数据是否已存在并实现新增逻辑
优惠活动
大模型
产品
解决方案
定价
更多

如何在Spring Reactive应用中检查数据是否已存在并实现新增逻辑

问题根因

你原有代码的核心问题是逻辑链路顺序错误:findByTitle返回的已存在图书对象、switchIfEmpty返回的新保存成功的图书对象,都会流入最后一段抛异常的flatMap,所以无论新增是否成功都会触发异常。

优化后实现代码

public Mono<Book> saveBook(Mono<Book> book) {
    return book
            .doOnNext(b -> log.info("Save book with title: {}", b.getTitle()))
            .flatMap(requestBook -> 
                // 先按书名查询是否已存在
                bookRepository.findByTitle(requestBook.getTitle())
                        // 查询到结果说明图书已存在,抛出异常
                        .flatMap(existedBook -> Mono.error(
                                new ResourceAlreadyExistsException(
                                        String.format("Book already exists for provided title :: %s", requestBook.getTitle())
                                )
                        ))
                        // 未查询到结果,执行保存逻辑
                        .switchIfEmpty(bookRepository.save(requestBook))
            );
}

逻辑说明

  • 整条响应式链路仅会在查询到已存在同名图书时触发异常分支
  • 无同名图书时直接进入switchIfEmpty执行保存,返回保存后的Book对象,不会触发异常逻辑
  • 去掉了方法上同步抛出ResourceAlreadyExistsException的声明,响应式场景下异常是封装在Mono的错误信号中传播的,无需同步声明抛出
  • 简化了保存逻辑,无需调用saveAll再取next,直接调用save方法传入实体即可

并发场景优化建议

如果有高并发写入的场景,建议给数据库表的title字段添加唯一索引,避免两个请求同时通过存在性校验后重复插入。可以额外添加异常适配逻辑:

public Mono<Book> saveBook(Mono<Book> book) {
    return book
            .doOnNext(b -> log.info("Save book with title: {}", b.getTitle()))
            .flatMap(requestBook -> 
                bookRepository.findByTitle(requestBook.getTitle())
                        .flatMap(existedBook -> Mono.error(
                                new ResourceAlreadyExistsException(
                                        String.format("Book already exists for provided title :: %s", requestBook.getTitle())
                                )
                        ))
                        .switchIfEmpty(bookRepository.save(requestBook))
            )
            // 捕获数据库唯一索引冲突异常,转换为自定义异常
            .onErrorResume(DuplicateKeyException.class, e -> 
                Mono.error(new ResourceAlreadyExistsException("Book already exists"))
            );
}

内容的提问来源于stack exchange,提问作者pjk

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.18 19:45:03