如何使用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,因此必须尝试对返回的值执行操作,而不检查它是否为空。
- Spring和hibernate.cfg.xml
- 何时使用Hibernate / JPA / Toplink?
- Spring-Hibernate在webapp中使用,什么是Thread安全会话管理的策略
- Spring Boot / Thymeleaf / Hibernate:带有Java注释的Sessionfactory Bean
- Weblogic错误:由以下原因引起:weblogic.transaction.internal.AppSetRollbackOnlyException:在事务上调用setRollbackOnly
- Spring Data配置 – 找不到hibernate.properties
- Hibernate 4 @OneToMany List
- 如何防止JPA回滚交易?
- 删除不使用JpaRepository