【问题标题】:How to properly handle empty resultset with Hibernate and Spring Boot如何使用 Hibernate 和 Spring Boot 正确处理空结果集
【发布时间】:2016-10-11 22:35:53
【问题描述】:

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

出现意外错误(类型=内部服务器错误, 状态=500)

在客户端,NullPointerException 在服务器端。

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

【问题讨论】:

  • 返回 404 Not Found。
  • 您能详细说明您的方法吗?

标签: java spring hibernate spring-mvc


【解决方案1】:

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

【讨论】:

    【解决方案2】:

    检查返回值,如果不是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&lt;T&gt;,如 comments 中提到的 JB Nizet。基本上,Optional&lt;T&gt; 只是一个容器,它可能保存也可能不保存 T 类型的值。您可以将此类型用作 Spring Data JPA 方法的返回类型,如下所示:
    public interface SomethingRepository extends CrudRepository<Something, Long> {
        Optional<Something> findById(Long id);
    }
    

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

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

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

    最后你的控制器会是这样的:

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


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

    【讨论】:

    • 或者你可以抛出一个异常并用@ResponseStatus(HttpStatus.NOT_FOUND)注释一些异常。结合 Spring-data-jpa 返回空 Optional 而不是 null 的可能性,您可以使用:Something something = somethingRepository.findById(id).orElseThrow(NotFoundException::new);
    • @JBNizet 是的,这是个好主意。
    • @JBNizet 用您的建议更新了答案。谢谢
    • 谢谢你,成功了。将“@ResponseStatus”和“@RequestMapping”放在我的控制器层或服务层会更好吗?
    • 最好不要将控制器特定的东西暴露到你的服务层中
    猜你喜欢
    • 2015-07-20
    • 1970-01-01
    • 2015-10-17
    • 2019-10-01
    • 2015-08-02
    • 2020-04-17
    • 1970-01-01
    • 2011-10-08
    • 1970-01-01
    相关资源
    最近更新 更多