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));
更笼统的说明:
- 值得看看
Mono
和 Flux
上可用的其他方法,就像您在使用 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
以便可以触发链中的下一个函数。
我想创建一个新的 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));
更笼统的说明:
- 值得看看
Mono
和Flux
上可用的其他方法,就像您在使用 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
以便可以触发链中的下一个函数。