Reputation: 599
I'm trying to query
the Database with a list of Id's
and, in case they don't exist, do some stuff with them.
My plan was to do something like
List<Optional<MyObject>> fingById(Set<String> myIds);
I understand this wont' work out of the box because I suppose that even if all the id's where present nothing guarantees me that they will be ordered, so if some of them are present I will get some random null optionals around which I won't be able to may to the Id that returned it.
Basically what I need to do in the end is to retrieve these objects, update one field or create them with default value if not present.
Which is the best way of doing this in batch?
Thanks :)
Upvotes: 3
Views: 338
Reputation: 44960
You could map the results by their id into Map<String, Optional<MyObject>>
and then fill in the blanks with Optional.empty()
.
List<MyObject> findByIdIn(Set<String> ids);
default Map<String, Optional<MyObject>> mapByIdIn(Set<String> ids) {
Map<String, Optional<MyObject>> found = findByIdIn(ids)
.stream()
.collect(Collectors.toMap(MyObject::getId, Optional::of));
ids.stream()
.filter(id -> !found.containsKey(id))
.forEach(id -> found.put(id, Optional.empty()));
return found;
}
Upvotes: 2
Reputation: 2863
I don´t think that it is a good idea to use a List
of Optional
values. Instead, I recommend to just use the default methods of the repository and query for all existing entities.
List<MyObject> findAll();
After that, you can iterate through all objects and check for missing ids. To improve performance, i recommend the useage of a Map
:
var objectMap = repository.findAll().stream()
.collect(Collectors.toMap(MyObject::getId, Function::Identity);
Then, you can simply check if any of the ids is contained in the map:
myIds.stream().filter(objectMap::contains)
.forEach({
// do some stuff, present id
});
myIds.stream().filter((id) -> !myMap.contains(id))
.forEach({
// do some stuff, not present id
});
Upvotes: 0