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


问题内容

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

发生意外错误(类型=内部服务器错误,状态= 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<T>,如JB
Nizet
评论中所述。基本上,Optional<T>它只是一个可能包含或可能不包含type值的容器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 FoundHTTP响应。

最终,您的控制器将像:

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

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