【问题标题】:Reactor : How to convert a Flux of entities into a Flux of DTO objectsReactor:如何将实体通量转换为 DTO 对象通量
【发布时间】:2020-02-29 08:54:36
【问题描述】:

我有一个用户实体和一个角色实体。除了 User 实体有一个对应于其各自角色的 id 的 role_id 字段之外,这些字段并不重要。由于 Spring Data R2DBC 不会在实体之间建立任何形式的关系,因此我转向 DTO 方法。我对 R2DBC 和响应式编程作为一个整体非常陌生,我一生无法弄清楚如何将 Flux<User> 转换为我的存储库的 findAll() 方法将我返回到 Flux<UserDto>。我的 UserDto 类非常简单:

@Data
@RequiredArgsConstructor
public class UserDto 
{
    private final User user;

    private final Role role;
}

这是我正在尝试制作的 UserMapper 类:

@Service
@RequiredArgsConstructor
public class UserMapper 
{
    private final RoleRepository roleRepo;

    public Flux<UserDto> map(Flux<User> users)
    {
        //???
    }
}

如何让这个映射器将Flux&lt;User&gt; 转换为包含用户各自角色的Flux&lt;UserDto&gt;

谢谢!

【问题讨论】:

    标签: java reactive-programming dto project-reactor spring-data-r2dbc


    【解决方案1】:

    假设您的 RoleRepository 有一个 findById() 方法或类似方法来查找给定其 ID 的 Role,并且您的用户对象有一个 getRoleId(),您可以通过标准 map 调用来完成:

    return users.map(u -> new UserDto(u, roleRepo.findById(u.getRoleId())));
    

    或者在findById()返回Mono的情况下:

    return users.flatMap(u -> roleRepo.findById(u.getRoleId()).map(r -> new UserDto(u, r)));
    

    如果getRoleId() 可能返回 null,您当然可能想要添加额外的检查。

    【讨论】:

    • 谢谢迈克尔!我头晕目眩,我正在使用 R2DBC 和 Webflux。我的目标是练习制作一个完全反应式的 REST API。有没有办法让您的解决方案变得完全被动?
    • 而且,我正在使用响应式存储库,因此 RoleRepository 的 findById() 方法返回 Mono 而不是 Role,因此我无法以这种方式构造 UserDto 对象。
    • @Martin 只需使用另一个级别的映射进行flatMap() 呼叫 - 请参阅我的更新答案。如果您使用的是 R2DBC,请忽略我关于使用有界弹性调度程序的 cmets。
    • MAN 这种反应性的东西很复杂!我希望建立这个项目能帮助我掌握这些概念。感谢上帝stackoverflow存在LOL。干杯!
    • 我用过 JPA 和 Hibernate 来回地狱。我认为这就是为什么很难掌握反应式概念的原因。熟能生巧!
    【解决方案2】:

    将数据从业务对象转换为数据库对象:

    private static UserDAO covertUserBOToBUserDAO(UserBO userBO){
        return new UserDAO(userBO.getUserId(), userBO.getName(), userBO.getMobileNumber(), 
         userBO.getEmailId(), userBO.getPassword());
    }
    

    将数据从数据库对象转换为业务对象:

    private static Mono<UserBO> covertUserDAOToBUserBO(UserDAO userDAO){
        return Mono.just(new UserBO(userDAO.getUserId(), userDAO.getName(), 
         userDAO.getMobileNumber(), userDAO.getEmailId(), userDAO.getPassword()));
    }
    

    现在异步服务(getAllUsers):

    public Flux<UserBO> getAllUsers(){
            return userRepository.findAll().flatMap(UserService::covertUserDAOToBUserBO);
    }
    

    由于 flatMap 是异步的,所以我们可以从异步操作中受益,甚至可以将对象从 DAO 转换为 BO。

    同样,如果保存数据然后我尝试如下:

    public Mono<UserBO> saveUser(UserBO userBO)
    {
            return 
     userRepository.save(covertUserBOToBUserDAO(userBO)).flatMap(UserService::covertUserDAOToBUserBO);
    }
    

    【讨论】:

      猜你喜欢
      • 2021-08-31
      • 2019-04-22
      • 2014-03-24
      • 1970-01-01
      • 2017-04-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多