如何在此 Java 8+ 应用程序中正确使用地图运算符以检索、修改和更新数据库上的对象?

How to correctly use the map operator in this Java 8+ application in order to retrieve, modify and update an object on the DB?

我正在开发一个基于 Spring Boot 的 Java 8+ 项目,我发现在尝试对我的代码使用“函数式”方法时遇到了一些困难。我承认我仍然使用 Java 7 方法,我正在尝试使用现代构造改进我的代码。

我有这个服务class方法:

/`
 * Deactivate an user retrieved by its user ID
 * @throws NotFoundException 
 */
@Override
public Optional<User> deactivateUser(int userId) throws NotFoundException {
    
    Optional<User> retrievedUser = this.userRepository.findById(userId);
    
    return Optional.ofNullable(retrievedUser)      
            .map((user) -> retrievedUser.get())
            .orElseThrow(() -> new NotFoundException(String.format("The user having ID %s was not found", userId))));
}

如您所见,它首先使用 Spring Data JPA 存储库检索 Optional<User> 对象。

然后我尝试使用功能方法(使用 map() 运算符)来实现以下行为:

  1. 检索包含在使用存储库检索的 Optional<User> 对象中的 User 对象。

  2. 如果检索到的 Optional<User> 对象不为空 --> 在 return 这个对象之前做一些操作。

  3. 如果检索到的 Optional<User> 对象为空 --> 抛出 NotFoundException() 异常。

我觉得第1点和第3点没问题。问题是我不明白如何正确地将一些逻辑放入 map() 函数中,目前我有这样的东西:

.map((user) -> retrievedUser.get())

具体是什么意思?我认为它将 retrievedUser.get() 检索到的 User 对象放入 returned 的 user 变量中。我的推理正确吗? (我完全不确定)。

我的问题是,在 return 这个 User 对象之前,我需要执行一些操作(基本上更新一个名为 isActive 的字段,将其设置为 false 然后使用 Spring Data JPA save() 方法更新它)。我该怎么做?你能举个例子吗?我认为对我来说这可能是一个例子,我在 map() 运算符中有一个多行函数(也是一个首先执行 retrievedUser.get() 操作并将其打印到另一行的函数,那么我应该能够自己执行所需的逻辑)。

您可以编写一个接受用户和 return 用户的函数来执行 (2) 的逻辑。例如:

public User processUser(User user) {
    user.setActive(false);
    return user;
}

然后在map算子中引用这个函数:

return Optional.ofNullable(retrievedUser
            .map((user) -> processUser(user))
            .orElseThrow(() -> new NotFoundException(String.format("The user having ID %s was not found", userId))));

您可以进一步使用方法参考将其简化为:

return Optional.ofNullable(retrievedUser
            .map(this::processUser)
            .orElseThrow(() -> new NotFoundException(String.format("The user having ID %s was not found", userId))));

map method takes a Function object as a parameter. The Function is a generic interface that only has one method that acts like a callback, so in order to achieve your desired result, you have to implement this interface and pass it to the method. To do so, you can implement it by using a lambda expression(这是您尝试做的方式)。在这种情况下,将调用该函数并传递您的存储库找到的对象。

你可能想要这样的东西:

    return Optional.ofNullable(retrievedUser)
        .map((user) -> {
            // do your operation with the object
            return user;
        })
        .map(updatedUser -> userRepository.save(updatedUser))
        .orElseThrow(() -> new NotFoundException(String.format("The user having ID %s was not found", userId))));

请注意,在 lambda 表达式中,您处理的是 User 而不是 Optional<User>,因此无需在此处使用 .get()。 您还应该注意 orElse/orElseThrow 类函数 return 对象的实例而不是 Optional,因此您必须更改 return 类型你的方法。

This article 如果想了解每个操作的作用以及如何使用它们,这是一本很好的读物。