处理 findAll() 上的空结果:列表是否有 orElseThrow()?
Handling empty results on findAll(): Is there a orElseThrow() for lists?
我正在创建一个 Spring REST 服务。我有一个 findById()
电话:
@GetMapping("/items/{id}")
MyItem one(@PathVariable String id) {
return repository.findById(id).orElseThrow(() -> new MyItemNotFoundException(id));
}
如果给定 id
没有 MyItem 对象,我将使用 Optional<T>.orElseThrow()
方法抛出异常。这个非常有用,也很简单。
现在我从 PagingAndSorting<T, ID>
存储库添加了一个 findAll()
调用:
@GetMapping("/items")
List<MyItem> all() {
return repository.findAll();
}
有没有一种简单的方法可以像处理单个项目那样处理空列表输出?或者我需要创建类似的东西:
@GetMapping("/items")
List<MyItem> all() {
List<MyItem> items = repository.findAll();
if (items.isEmpty())
throw new MyItemNotFoundException();
return items;
}
(真实用例处理一些请求参数来过滤整个列表)
您可以流式传输列表,得到 Optional
和 findAny
,如果结果不为空,则映射回列表:
items.stream().findAny().map((e) -> items).orElseThrow(NotFoundException::new);
但是您应该考虑这是否真的需要导致异常。作为搜索功能的消费者,我的期望是一个空结果,没有任何元素符合我的标准。
findById
中 Optional
背后的原因是它避免返回 null
。
另一方面,空集合可以安全地迭代和处理,因此没有内置特殊的 .throwIfEmpty()
机制。空集合本身本质上是一个 Optional。它不是空的,可能包含也可能不包含元素。
如果在您的业务逻辑中没有结果意味着错误,那么由您来处理。
对于 REST,这是你应该做的 return:
- 未找到单个元素:抛出异常 - 映射 404 响应代码
- 空列表:return 状态代码为 - 200 的空列表
解决方案可以是包装 findAll
调用的实用函数。
public class MyItemNotFoundException ... {
public static <T> List<T> requireNotEmpty(List<T> items) throws MyItemNotFoundException {
if (items.isEmpty()) {
throw new MyItemNotFoundException();
}
return items;
}
}
@GetMapping("/items")
List<MyItem> all() {
return MyItemNotFoundException.requireNotEmpty(repository.findAll());
}
将函数放在 MyItemNotFoundException 中可读性不是很好。
一个更好的名字仍然感觉做作:
return MyItemNotFoundException.whenEmpty(repository.findAll());
但你会找到一个地方,也许在某个基地class/interface。
(在某些系统中,存储库 findAll 可能 return null(非常丑陋),并且具有这样的包装功能也可以处理。)
我正在创建一个 Spring REST 服务。我有一个 findById()
电话:
@GetMapping("/items/{id}")
MyItem one(@PathVariable String id) {
return repository.findById(id).orElseThrow(() -> new MyItemNotFoundException(id));
}
如果给定 id
没有 MyItem 对象,我将使用 Optional<T>.orElseThrow()
方法抛出异常。这个非常有用,也很简单。
现在我从 PagingAndSorting<T, ID>
存储库添加了一个 findAll()
调用:
@GetMapping("/items")
List<MyItem> all() {
return repository.findAll();
}
有没有一种简单的方法可以像处理单个项目那样处理空列表输出?或者我需要创建类似的东西:
@GetMapping("/items")
List<MyItem> all() {
List<MyItem> items = repository.findAll();
if (items.isEmpty())
throw new MyItemNotFoundException();
return items;
}
(真实用例处理一些请求参数来过滤整个列表)
您可以流式传输列表,得到 Optional
和 findAny
,如果结果不为空,则映射回列表:
items.stream().findAny().map((e) -> items).orElseThrow(NotFoundException::new);
但是您应该考虑这是否真的需要导致异常。作为搜索功能的消费者,我的期望是一个空结果,没有任何元素符合我的标准。
findById
中 Optional
背后的原因是它避免返回 null
。
另一方面,空集合可以安全地迭代和处理,因此没有内置特殊的 .throwIfEmpty()
机制。空集合本身本质上是一个 Optional。它不是空的,可能包含也可能不包含元素。
如果在您的业务逻辑中没有结果意味着错误,那么由您来处理。
对于 REST,这是你应该做的 return:
- 未找到单个元素:抛出异常 - 映射 404 响应代码
- 空列表:return 状态代码为 - 200 的空列表
解决方案可以是包装 findAll
调用的实用函数。
public class MyItemNotFoundException ... {
public static <T> List<T> requireNotEmpty(List<T> items) throws MyItemNotFoundException {
if (items.isEmpty()) {
throw new MyItemNotFoundException();
}
return items;
}
}
@GetMapping("/items")
List<MyItem> all() {
return MyItemNotFoundException.requireNotEmpty(repository.findAll());
}
将函数放在 MyItemNotFoundException 中可读性不是很好。 一个更好的名字仍然感觉做作:
return MyItemNotFoundException.whenEmpty(repository.findAll());
但你会找到一个地方,也许在某个基地class/interface。
(在某些系统中,存储库 findAll 可能 return null(非常丑陋),并且具有这样的包装功能也可以处理。)