微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

在 Spring WebFlux 中,如何链接多个服务/存储库中的方法,以便“删除”多个 DB-Collections 中的元素? 1.1) 代码:

如何解决在 Spring WebFlux 中,如何链接多个服务/存储库中的方法,以便“删除”多个 DB-Collections 中的元素? 1.1) 代码:

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) 问题:


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))
                 );
 }

非常感谢您的帮助

解决方法

假设您的 someclass.delete() 操作返回 Mono<Something>

主要问题是 map 不会订阅内部发布者。

这里必须使用 flatMap/concatMap... 操作,它们会订阅内部发布者(例如 xyz.delete)

如果您的删除方法没有返回已删除的项目,您可以使用 then(object) 以给定参数返回。

正如我所见,您不能同时执行所有删除操作,而是按顺序执行所有删除操作,因为每个操作的输入参数都是前一个操作的输出。如果您考虑批量处理所有帖子或评论......同时删除,那是可能的。您可以 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()


    }
    
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。