【问题标题】:What is a good way to handle an Optional<User> object returned by a Spring Data JPA repository in a situation like this?在这种情况下,处理 Spring Data JPA 存储库返回的 Optional<User> 对象的好方法是什么?
【发布时间】:2022-01-10 12:01:41
【问题描述】:

我正在开发一个 Spring Boot 应用程序。进入服务类我有这个服务方法:

@Override
public User getUserById(Integer userId) {
    Optional<User> retrievedUser = this.userRepository.findById(userId);
    return retrievedUser.get();
}

像往常一样,它调用 Spring Data JPA findById() 方法返回一个 Optional 对象。

我正在返回 User 对象。在这里我有以下疑问:如果 Optionalempty,那么当我执行此操作时它会抛出异常:

retrievedUser.get()

所以现在......当我有一个 Optional 对象时,处理这种情况的最常见方法是什么。

前面的服务方法被调用到实现API的控制器方法中,这个:

@ApiOperation(
          value = "Retrieve an user by its id", 
          notes = "",
          produces = "application/json")
@GetMapping(value = "/{useridOrEmail}", produces = "application/json")
public ResponseEntity<User> getUserByIdOrEmail(@PathVariable("useridOrEmail") String userIdOrEmail,
                                        @RequestParam(value="isEmail", required = false, defaultValue = "false") boolean isEmail) 
                            throws NotFoundException  {
    
    log.info(String.format("****** Retrieve the user having ID or email: %s *******", userIdOrEmail));
    
    User retrievedUser = null;
    
    if(!isEmail)
        retrievedUser = this.userService.getUserById(Integer.parseInt(userIdOrEmail));
    else
        retrievedUser = this.userService.getUserByemail(userIdOrEmail);
    
    if (retrievedUser == null) {
        String ErrMsg = String.format("The user having ID or email %s was not found", userIdOrEmail);
        
        log.warning(ErrMsg);
        
        throw new NotFoundException(ErrMsg);
    }
        
    return new ResponseEntity<User>(retrievedUser, HttpStatus.OK);
        
}

正如您在我的控制器方法中看到的,我正在检查上一个服务的结果是否为空,以防抛出异常。此异常由扩展 ResponseEntityExceptionHandler 的类处理,以创建正确的响应。

所以我的想法是改变我的服务方法,将这个 retrivedUser.get() 操作放入 try catch。如果我获得异常,我的 getUserById() 服务方法将返回 null ,因此我的控制器方法将抛出 NotFoundException 异常,该异常将被处理返回Spring 的特定错误响应。

可能是一个很好的解决方案或存在更好的方法来处理这种情况?

【问题讨论】:

  • 如果您已经有特定类型异常的异常处理程序,那么我认为可以将 NoSuchElementException 转换为您正在使用的任何类型。尽管这种方法不是很有趣,但在 java 中我看不到其他可以做的事情。
  • 为什么不从服务返回Optional,然后返回this.userService.getUserById(Integer.parseInt(userIdOrEmail)).orElseThrow(() -&gt; new NotFoundException(String.format("The user having ID or email %s was not found", userIdOrEmail)))
  • 为什么不简单地将orElseThrow 放在负责业务逻辑的服务中?
  • "所以我的想法是改变我的服务方法,将这个 retrievedUser.get() 操作放入 try catch。" - 或者更简单:使用Optional::orElseThrow。我同意移动抛出Exception 的逻辑应该是服务方法的一部分。

标签: java spring-boot java-8 spring-data-jpa


【解决方案1】:

我会从服务中返回 Optionals,然后你可以像这样很好地链接它们:

public ResponseEntity<User> getUserByIdOrEmail(@PathVariable("useridOrEmail") String userIdOrEmail,
                                        @RequestParam(value="isEmail", required = false, defaultValue = "false") boolean isEmail) 
                            throws NotFoundException  {
    
    log.info(String.format("****** Retrieve the user having ID or email: %s *******", userIdOrEmail));
    return fetchUser(userIdOrEmail, isEmail)
           .map((user) -> new ResponseEntity<User>(user, HttpStatus.OK))
           .orElseThrow(() -> new NotFoundException(String.format("The user having ID or email %s was not found", userIdOrEmail)));
}

private Optional<User> fetchUser(String idOrEmail, boolean isEmail) {
    return isEmail 
           ? this.userService.getUserByemail(idOrEmail)
           : this.userService.getUserById(Integer.parseInt(idOrEmail));
}

并且记录警告应该在一个通用的异常处理程序中处理,该处理程序记录所有未找到的类似方式。

【讨论】:

    【解决方案2】:

    一个好的方法是接受数据库返回的任何内容。然后控制器应该决定做什么:

    Optional<User> retrievedUser = isEmail
       ? this.userService.getUserByemail(userIdOrEmail)
       : this.userService.getUserById(Integer.parseInt(userIdOrEmail));
        
    if (!retrievedUser.isPresent()) {
       String ErrMsg = String.format("The user having ID or email %s was not found", userIdOrEmail);
       log.warning(ErrMsg);
       throw new NotFoundException(ErrMsg);
    }
    
    return new ResponseEntity<User>(retrievedUser.get(), HttpStatus.OK);
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-04-16
      • 1970-01-01
      • 2017-09-17
      • 1970-01-01
      • 2020-09-14
      • 2016-02-15
      • 2022-10-13
      相关资源
      最近更新 更多