如何使用Hibernate和Spring Boot正确处理空结果集

我有一个使用Hibernate和Spring Data JPA的CrudRepository的Spring应用程序。 如果查询的数据存在于数据库中,则一切似乎都能正常工作。 但是,如果存在不返回结果的查询,则CrudRepository返回null并且我得到NullPointerException 。 所以例如http://localhost:8080/api/id=3如果数据库中有一个http://localhost:8080/api/id=3的行,它可以正常工作。 如果没有id为3的行,则失败并显示:

出现意外错误(type = Internal Server Error,status = 500)

在客户端和服务器端的NullPointerException

处理“无结果”查询的简单情况的正确方法是什么?

检查返回值,如果它不为null ,则返回一些表示为200 OK响应。 否则,返回404 Not Found 。 最后,你会有一个像这样的控制器:

 @RequestMapping(...) public ResponseEntity getOne(...) { Something something = repository.findOne(...); if (something == null) return ResponseEntity.notFound().build(); return ResponseEntity.ok(something); } 

您可以重构前面的代码以合并Java 8的Optional ,正如JB Nizet在评论中提到的那样。 基本上, Optional只是一个容器,可能包含也可能不包含T类型的值。 您可以使用此类型作为Spring Data JPA方法的返回类型,如下所示:

 public interface SomethingRepository extends CrudRepository { Optional findById(Long id); } 

然后为404 Not Found定义一个例外:

 @ResponseStatus(HttpStatus.NOT_FOUND) public class NotFoundException extends RuntimeException {} 

如果在控制器中抛出NotFoundException类型的exception,Spring MVC的exception解析器将捕获该exception并将其转换为404 Not Found HTTP响应。

最后你的控制器就像:

 @RequestMapping(...) public Something getOne(...) { return repository.findById(id).orElseThrow(NotFoundException::new); } 

有关以下内容的更详细讨论

  • Spring Data JPA的Optional支持, 请阅读此处 。
  • Spring MVC的exception解析器,请阅读此处 。
  • Java 8的Optional , 请阅读此处 。
  • REST最佳实践,您可以查看REST in Practice一书。

如果没有返回结果,则spring crud存储库查找方法都不会抛出exception。 它们都返回null。 由于在服务器端获得空指针exception,因此必须尝试对返回的值执行操作,而不检查它是否为空。