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

Kev*_*sko 6 java spring hibernate spring-mvc

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

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

在客户端和NullPointerException服务器端.

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

Ali*_*ani 15

检查返回值,如果不是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);
}
Run Code Online (Sandbox Code Playgroud)


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

public interface SomethingRepository extends CrudRepository<Something, Long> {
    Optional<Something> findById(Long id);
}
Run Code Online (Sandbox Code Playgroud)

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

@ResponseStatus(HttpStatus.NOT_FOUND)
public class NotFoundException extends RuntimeException {}
Run Code Online (Sandbox Code Playgroud)

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

最后你的控制器就像:

@RequestMapping(...)
public Something getOne(...) {
    return repository.findById(id).orElseThrow(NotFoundException::new);
}
Run Code Online (Sandbox Code Playgroud)


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

  • 或者,您可以抛出一个异常,并用@ResponseStatus(HttpStatus.NOT_FOUND)标注一些异常。结合Spring-data-jpa返回空的Optional而不是null的可能性,您可以使用:`something something = somethingRepository.findById(id).orElseThrow(NotFoundException :: new);` (2认同)