在 Spring WebFlux 中,如何链接来自多个服务/存储库的方法,以便“删除”多个 DB-Collections 中的元素?
Posted
技术标签:
【中文标题】在 Spring WebFlux 中,如何链接来自多个服务/存储库的方法,以便“删除”多个 DB-Collections 中的元素?【英文标题】:In Spring WebFlux, How to chaining methods from multiple services/repo, in order to 'delete' elements in multiples DB-Collections'? 【发布时间】:2021-08-26 16:15:14 【问题描述】:1) 关于问题的语境化:
我正在尝试使用 03 个不同的服务/存储库(userService + postService + userRepo)在 03 个不同的 DB-Collections(Reactive MongoDB)中“删除”项目;
我的目标是使用相同的链接代码同时删除一个对象(在每个集合中);
下面是上述情况的代码:
1.1) 代码:
当前工作状态:不工作;
当前行为:不执行任何删除,无论是 delete-userService、delete-postService 还是 delete-userRepo。
@Slf4j
@Service
@AllArgsConstructor
public class UserService implements UserServiceInt
private final UserRepo userRepo;
private final PostServiceInt postServ;
private final CommentServiceInt comServ;
private final CustomExceptions customExceptions;
@Override
public Mono<Void> deleteInThreeCollections(String id)
return userRepo
.findById(id)
.switchIfEmpty(customExceptions.userNotFoundException())
.map(user ->
userRepo.delete(user); // First deletion - delete-method from userRepo
return user;
)
.flatMapMany(user -> postServ.findPostsByAuthorId(user.getId()))
.map(post ->
postServ.delete(post); // Second deletion - delete-method from postService
return post;
)
.flatMap(post -> comServ.findCommentsByPostId(post.getPostId()))
.map(comServ::delete) // Third deletion - delete-method from commentService
.then()
;
2) 问题:
如何删除不同 DB-Collections 中的不同元素, 仅使用一个“链式删除方法”,该方法使用三个“删除方法” 三种不同的服务/repo(userService + postService + userRepo?3) 更新:
找到解决方案
@Override
public Mono<Void> deleteInThreeCollections(String id)
return userRepo
.findById(id)
.switchIfEmpty(customExceptions.userNotFoundException())
.flatMap(
user -> postServ
.findPostsByAuthorId(user.getId())
.flatMap(
post -> comServ.findCommentsByPostId(
post.getPostId())
.flatMap(comServ::delete)
.thenMany(
postServ.findPostsByAuthorId(
post.getAuthor()
.getId()))
.flatMap(postServ::delete)
)
.then(userRepo.delete(user))
);
非常感谢您的帮助
【问题讨论】:
【参考方案1】:假设您的someclass.delete()
操作返回Mono<Something>
。
主要问题是map
不会订阅内部发布者。
这里你必须使用flatMap
/concatMap
...操作,它们会订阅内部发布者(例如xyz.delete)
如果你的delete方法没有返回被删除的项,你可以使用then(object)
返回给定的参数。
正如我所见,您不能同时执行所有删除操作,而是按顺序执行,因为每个操作的输入参数都是前一个操作的输出。如果您考虑批量处理所有帖子或 cmets.. 同时删除,这是可能的。您可以collectList
id-s 并创建批处理操作 (deleteByIdIn(list of ids)
) 或创建并行通量并同时运行删除操作(批处理更好)。
在这里,我创建了一个带有假服务的最小示例来演示它:
import org.junit.jupiter.api.Test
import reactor.core.publisher.Flux
import reactor.core.publisher.Mono
import reactor.test.StepVerifier
data class User(
val id: String
)
data class Post(
val id: String
)
data class Comment(
val id: String
)
class UserRepo
fun finById(id: String): Mono<User>
println("Find an user")
return Mono.just(User("1"))
//example if delete gives back the object
fun delete(user: User): Mono<User>
println("delete $user")
return Mono.just(user)
class PostServiceInt
fun findPostsByAuthorId(userId: String): Flux<Post> = Flux.fromIterable(listOf(Post("1"), Post("2")))
//and if not
fun delete(post: Post): Mono<Void>
println("delete $post")
return Mono.empty()
class CommentServiceInt
fun findCommentsByPostId(postId: String): Flux<Comment> = Flux.fromIterable(listOf(Comment("10"), Comment("7"),Comment("3"),Comment("4")))
fun delete(comment: Comment): Mono<Comment>
println("delete $comment")
return Mono.just(comment)
class Example
val userRepo = UserRepo()
val postServ = PostServiceInt()
val comServ = CommentServiceInt()
@Test
fun test()
val result = userRepo.finById("1")
.switchIfEmpty(Mono.error RuntimeException() )
.flatMap user -> userRepo.delete(user)
.flatMapMany user -> postServ.findPostsByAuthorId(user.id)
.flatMap post -> postServ.delete(post).then(Mono.just(post))
.flatMap post -> comServ.findCommentsByPostId(post.id)
.flatMap comment -> comServ.delete(comment)
StepVerifier.create(result)
.expectNextCount(4)
.verifyComplete()
【讨论】:
伙计,非常感谢。你的帮助非常有帮助。感谢您花时间帮助我。非常感谢以上是关于在 Spring WebFlux 中,如何链接来自多个服务/存储库的方法,以便“删除”多个 DB-Collections 中的元素?的主要内容,如果未能解决你的问题,请参考以下文章
我们可以在 Spring Webflux 中使用 web servlet 和 servlet 过滤器吗?
服务器发送事件 Spring Webflux 返回事件名称以响应来自休息控制器的响应
在 spring boot 基于 webflux 的微服务中,订阅者是谁?