Webflux 更新对象并返回另一个

Webflux updating object and returning another

我想创建一个新的 ProjectGroup 对象,在它发生之前我想检查具有 owner_id 的用户是否具有角色 GROUP_OWNER,如果他没有那么我想添加它。

一切正常,直到我想将用户保存到不起作用的数据库(保存 ProjectGroup 工作正常)。

有人知道怎么解决吗?

    public Mono<ProjectGroup> create(ProjectGroup p) {
    return userRepository.findByUsername(p.getOwner_id()).flatMap(user -> {
        if (user != null) {
            if (!user.getRoles().contains(User.Role.GROUP_OWNER)) {
                List<User.Role> roles = user.getRoles();
                roles.add(User.Role.GROUP_OWNER);
                user.setRoles(roles);
                userRepository.save(user);
                return groupRepository.save(p);
            }
            return groupRepository.save(p);
        } else return null;
    });
}

记住使用 reactor 时的一般规则 - 订阅之前什么都不会发生。在 Webflux 领域,它是框架进行订阅,但这个概念仍然适用;你必须主动return一个发布者,这样框架才有机会订阅它,否则它永远不会被执行。

在此示例中,假设您的存储库是反应性的,那么 userRepository.save() 将 return 一个 Mono - 而您只是忽略 returned Mono,这意味着(根据上面的解释)保存永远不会发生。

相反,您想要 return 一个 Mono 来组合您的两个结果 - 也就是说,首先执行 userRepository.save(user)(并忽略 returned 值) ,然后执行 groupRepository.save(p)There's a dedicated method for this purpose,所以你可以简单地做:

return userRepository.save(user).then(groupRepository.save(p));

更笼统的说明:

  • 值得看看 MonoFlux 上可用的其他方法,就像您在使用 reactor 一样,您不可避免地会发现自己经常使用它们。
  • 反应流中不允许
  • null - 因此您的 if (user != null) { 检查是多余的。

当您调用 userRepository.save(user); 时,您正在打破链条,因为您忽略了 return 值,因此该行将永远不会被执行。

你应该做你想做的,然后执行下一部分。这可以通过多种方式完成,这是一种方式。

return userRepository.findByUsername(p.getOwner_id()) // This should return empty if nothing is found
    .flatMap(user -> {
        if (!user.getRoles().contains(User.Role.GROUP_OWNER)) {
            final List<User.Role> roles = user.getRoles();
            roles.add(User.Role.GROUP_OWNER);
            user.setRoles(roles);
            return userRepository.save(user);
        }
        return user;
    }
}).then(groupRepository.save(p));

你永远不应该 return null,并避免在反应式编程中进行 null 检查。如果您希望从函数中 return “什么都不做”,您应该 return a Mono#empty 以便可以触发链中的下一个函数。