epsilonmajorquezero
epsilonmajorquezero

Reputation: 599

How to mimic List<Optional<T>> like behaviour in Spring Data Repo?

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

Answers (2)

Karol Dowbecki
Karol Dowbecki

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

Glains
Glains

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

Related Questions