Kotlin WebFlux中基于邮箱唯一性条件写入MongoDB用户数据
解决Reactive Spring Data MongoDB邮箱唯一的创建逻辑
这问题我熟,用Reactive的操作符链式处理就能完美实现需求,咱们直接完善你的create方法:
完整实现代码
@Component("userService") class UserService(private val repository: UserRepository){ fun checkIfEMailExists(email: String): Mono<Boolean> { return repository.findByEMail(email).hasElement() } fun create(user: User): Mono<User> { return checkIfEMailExists(user.email) // 只保留邮箱不存在的情况(结果为false时才继续流) .filter { exists -> !exists } // 邮箱不存在时执行存储操作 .flatMap { repository.save(user) } // 邮箱已存在时返回明确的错误信息 .switchIfEmpty(Mono.error(IllegalArgumentException("该邮箱已被注册,请更换其他邮箱"))) } }
逻辑拆解
我给你一步步解释每个操作符的作用:
checkIfEMailExists(user.email):先获取目标邮箱是否已存在的响应式结果(Mono<Boolean>)filter { !exists }:过滤掉邮箱已存在的情况(也就是当结果为true时,这个流会变成空的),只让“邮箱不存在”的情况继续往下走flatMap { repository.save(user) }:当邮箱不存在时,执行MongoDB的存储操作,返回存储后的用户对象的Mono<User>switchIfEmpty(...):如果前面的filter把流变成了空(说明邮箱已存在),就返回一个包含自定义异常的Mono,这样调用方可以通过onErrorMap、onErrorResume等操作符处理这个异常场景
可选优化(简化代码)
如果checkIfEMailExists方法只有这里用到,还可以直接把逻辑合并到create里,减少一层方法调用:
fun create(user: User): Mono<User> { return repository.findByEMail(user.email) .hasElement() .filter { !it } .flatMap { repository.save(user) } .switchIfEmpty(Mono.error(IllegalArgumentException("Email already exists"))) }
注意事项
别忘了Reactive编程的核心特性:所有操作都是懒执行的,只有当订阅者订阅这个Mono<User>时,整个逻辑流才会实际执行,所以一定要确保返回完整的流,不能中途断链。
内容的提问来源于stack exchange,提问作者lucniner
相关产品推荐
相关产品推荐

