【问题标题】:How can I correctly use the stream map() in this use case involving the conversion of an entity class instance into a DTO instance?在这个涉及将实体类实例转换为 DTO 实例的用例中,如何正确使用流映射()?
【发布时间】:2022-01-18 22:48:27
【问题描述】:

我正在开发一个 Spring Boot 应用程序,并且我正在尝试使用更现代的(Java 8+ 构造),但我发现尝试对现有代码实施以下更改时遇到了一些困难。

我有如下服务方式:

@Override
public Optional<User> activateDeactivateUser(int userId, boolean isActive) throws NotFoundException {
    
    Optional<User> retrievedUser = this.userRepository.findById(userId);
    
    if(retrievedUser.isEmpty())
        throw new NotFoundException(String.format("The user having ID or email %s was not found", userId));
    
    
    return Optional.ofNullable(retrievedUser) 
            .map((user) -> { 
                log.info(String.format("****** USER E-MAIL *******", user.get().getEmail()));
                
                user.get().set_active(isActive);
                this.userRepository.save(user.get());
                
                return user;
                })
            .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userId)));
}

如您所见,此方法返回一个 可选 对象。首先,我不确定返回 Optional 是否是一种好习惯(因为如果它为空,我将抛出并处理 NotFoundException)。

但主要问题是我的 User 类是一个实体类(我正在使用 Hibernate,因此它包含表映射)我想更改以前的方法以检索 UserDTO 对象。

为了将 User 实例转换为 UserDTO 实例,我将这个 ConversionService 注入到我的服务类中(我在其他地方使用过)

@Autowired
ConversionService conversionService;

我的主要问题是,在我以前的方法中,我使用的是 ma​​p() 运算符。我曾尝试用这种方式改变之前的服务方式:

@Override
public UserDTO activateDeactivateUser(int userId, boolean isActive) throws NotFoundException {
    
    Optional<User> retrievedUser = this.userRepository.findById(userId);
    User userToBeUpdated = null;
    
    if(retrievedUser.isEmpty())
        throw new NotFoundException(String.format("The user having ID or email %s was not found", userId));
    else
        userToBeUpdated = retrievedUser.get(); 
    
    return userToBeUpdated
            .map((userToBeUpdated) -> { 
                log.info(String.format("****** USER E-MAIL *******", userToBeUpdated.getEmail()));
                
                userToBeUpdated.set_active(isActive);
                this.userRepository.save(userToBeUpdated);
                
                return userToBeUpdated;
                })
            .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userId)));

}

我的想法是使用 ma​​p() 方法将一个对象(我的 User 对象转换为 UserDTO 对象并保存它在数据库上应用一个函数)。

首先 Eclipse 它在 ma​​p() 方法调用上给我以下错误:

方法 map(( userToBeUpdated) -> {}) 未定义 输入用户

由于我对流的经验很少,我不知道它是否是 ma​​p() 使用的正确用例。这是因为(也在第一个方法实现中,效果很好)我没有实现真正的对象转换,但我正在更改对象字段的值,然后将其保存到数据库中。在第二种情况下(我的服务方法的第二个版本),我必须从 User 转换为 UsertDTO

我错过了什么?在这个用例中使用 ma​​p() 是否合法,还是强制使用 map() 的预期方式?有什么好的方法可以解决这个问题?

【问题讨论】:

    标签: java spring-boot java-8 java-stream java-14


    【解决方案1】:

    在第一个示例中,if 语句完全没有意义。您可以完全删除它,因为如果返回的实际值不是nullOptional 上的map 将被执行。此外,NotFoundException 存在重复代码。

    @Override
    public UserDTO activateDeactivateUser(int userId, boolean isActive) throws NotFoundException {
        return this.userRepository.findById(userId)
                .map((userToBeUpdated) -> {
                    log.info(String.format("****** USER E-MAIL *******", userToBeUpdated.getEmail()));
    
                    userToBeUpdated.set_active(isActive);
                    this.userRepository.save(userToBeUpdated);
    
                    return userToBeUpdated;
                })
                .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userId)));
    
    }
    

    尽管这段代码可能有效,但问题是我们在 map 的 lambda 内部有一个副作用。当我们将其作为映射操作的高阶函数传递时,建议使用纯函数。使用这样的东西可能会更好:

    @Override
    public User activateDeactivateUser(int userId, boolean isActive) throws NotFoundException {
    
        User retrievedUser = this.userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userId)));
    
        retrievedUser.set_active(isActive);
        this.userRepository.save(retrievedUser);
    
        return retrievedUser;
    }
    

    现在,您的第二个示例问题更大。这个sn-p是无效的,逻辑上没有意义:

    userToBeUpdated
                .map((userToBeUpdated) -> {...})
    

    User 类是一个休眠实体,它很可能没有实现map 方法,为什么会这样?在 Java 中,流和选项通常为 map 提供实现。它用于对流/可选封装的每个对象应用一些转换。您可能需要查看 streamsoptionals 的文档以了解有关它们的更多信息。

    我相信你想在这里做的是:

    @Override
    public UserDTO activateDeactivateUser(int userId, boolean isActive) throws NotFoundException {
    
        User retrievedUser = this.userRepository.findById(userId)
                .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userId)));
    
        retrievedUser.set_active(isActive);
        this.userRepository.save(retrievedUser);
    
        return conversionService.convert(retrievedUser);
    }
    

    我希望ConversionService 有类似convert 的方法,它接受一个实体对象并返回一个DTO。

    其他一些与问题无关的注释:

    • 请遵守 Java 编码标准。在 Java 中,我们不使用蛇形大小写进行方法调用。这个userToBeUpdated.set_active(isActive); 应该是这样的userToBeUpdated.setActive(isActive);

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-05-29
      • 2010-11-13
      • 1970-01-01
      • 2020-09-20
      • 2019-08-08
      • 1970-01-01
      相关资源
      最近更新 更多