如何使用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 Found
HTTP响应。
最终,您的控制器将像:
@RequestMapping(...)
public Something getOne(...) {
return repository.findById(id).orElseThrow(NotFoundException::new);
}
有关以下内容的详细讨论:
- Spring Data JPA的
Optional<T>
支持,请在此处阅读。 - Spring MVC的异常解析器,请阅读此处。
- Java 8
Optional<T>
,在这里阅读。 - REST最佳实践,您可以查看REST in Practice书。