2

Using a ReactiveMongoRepository and a custom method to return all objects with the matching property is returning a empty collection on anything other than the findAllById call.

I'm wondering if I just misunderstood something here and this only works on the ID field or something?

The interface I'm using:

@Repository
public interface VideoRepository extends ReactiveMongoRepository<Video, String> {
    Flux<Video> findAllByHash(Iterable<Long> hash);
}

And I'm just calling that via:

@GetMapping("duplicates")
public Flux<Video> duplicates() {
    // {...}

    List<Long> hashList = duplicateDTOs
            .stream()
            .map(duplicateDTO -> Long.valueOf(duplicateDTO.getHash()))
            .collect(Collectors.toList());

    return videoRepository.findAllByHash(hashList);
}

For reference, the POJO in question:

@Data
@Builder
@Document
@AllArgsConstructor
@NoArgsConstructor
public class Video {

    @Id
    String id;

    long hash;

    //{...}
}

I have confirmed I'm passing in three values in the hashList which match the custom hash property set on the Video POJO.

Should this not return all Video objects which have the matching custom hash property as it does when I do the same thing but for the id property?

1 Answer 1

2
findAllByHashIn(Collection<Long> hashes);

I've never used an Iterable as a parameter to a custom JPA repository method before, but I would translate the name findAllByHash as "take a single hash value and find all entries possessing that value" and the signature would be findAllByHash(Long hash).

Your motivation is a bit different: you want all hashes to be used during the search. According to this table,

Keyword | Sample                             | JPQL snippet

In      | findByAgeIn(Collection<Age> ages)  | … where x.age in ?1

Spring JPA support logical IN and accepts a subclass of Collection, so it could be

findAllByHashIn(Collection<Long> hashes);
findAllByHashIn(List<Long> hashes);

Update

Out of curiosity, I wrote own Iterable which isn't a Collection to see the method fail. As expected, Spring threw

IllegalArgumentException: Parameter value XXX did not match expected type [java.lang.Long (n/a)].

Although it expects a Long parameter, it runs well with a Collection (I used Arrays.asList(1L, 2L)), but executes a silly SQL query:

... from XXX XXX0_ where XXX0_.hash=(? , ?)
binding parameter [1] as [BIGINT] - [1]
binding parameter [2] as [BIGINT] - [2]

With findAllByHashIn, IN is added and the query looks nice:

... from XXX XXX0_ where XXX.hash in (? , ?)
binding parameter [1] as [BIGINT] - [1]
binding parameter [2] as [BIGINT] - [2]
Sign up to request clarification or add additional context in comments.

2 Comments

That is very interesting, I am able to successfully make use of Flux<Video> findAllByHashIn(Iterable<Long> hash); with no errors and the correct values being returned. Thank you though for spotting my obvious mistake, I've clearly been awake to long now.
@ChrisTurner happy to help :) I still don't recommend using Iterable as a method param though

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.