Handling empty results on findAll(): Is there a orElseThrow() for lists?

随声附和 提交于 2020-06-29 03:56:05

问题


I am creating a little Spring REST service. I have a findById() call:

@GetMapping("/items/{id}")
MyItem one(@PathVariable String id) {
    return repository.findById(id).orElseThrow(() -> new MyItemNotFoundException(id));
}

If there is no MyItem object with the given id, I am throwing an exception using the Optional<T>.orElseThrow() method. This is very useful and quite simple.

Now I added a findAll() call from the PagingAndSorting<T, ID> repository:

@GetMapping("/items")
List<MyItem> all() {            
    return repository.findAll();
}

Is there a simple way to handle empty list outputs in a similar way as it can be done with single items? Or do I need to create something like:

@GetMapping("/items")
List<MyItem> all() {    
    List<MyItem> items = repository.findAll();
    if  (items.isEmpty())
        throw new MyItemNotFoundException();        

    return items;
}

(The real use case handles some request parameters to filter the whole list)


回答1:


The reasoning behind the Optional in findById is that it avoids returning a null.

Empty collections on the other hand are safe to iterate and handle, so there's no special .throwIfEmpty() mechanism built-in. An empty collection is essentially an Optional in itself. It's not null, and may or may not contain elements.

If in your business logic no results means error, then it's up to you to handle it.




回答2:


The solution could be a utility fuction wrapping the findAll call.

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());
}

Placing the function in the MyItemNotFoundException is not very readable. A better name still feels artificial:

    return MyItemNotFoundException.whenEmpty(repository.findAll());

But you'll find a place, maybe in some base class/interface.

(In some systems the repository findAll may return null (very ugly), and with such a wrapping function that can be dealt with too.)




回答3:


You could stream the list, get an Optional with findAny and map back to the list if the result is non-empty:

items.stream().findAny().map((e) -> items).orElseThrow(NotFoundException::new);

But you should consider if this really needs to result in an Exception. My expectation as consumer of a search function would be an empty result, of no element matches my criteria.




回答4:


By REST this is what you should return:

  • Single element not found: throw an exception - 404 response code mapped
  • Empty list: return empty list with - 200 status code


来源:https://stackoverflow.com/questions/57989531/handling-empty-results-on-findall-is-there-a-orelsethrow-for-lists

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!