Home > Blockchain >  JPA Specifications not working when trying to OR predicates together
JPA Specifications not working when trying to OR predicates together

Time:05-25

I'm having trouble trying to get a working Specification for this query. My data model looks something like this:

            Item { 
                Person person, 
                Place place
            }

            Person {
                Address address
            }

            Place {
                Address address
            }

            Address {
                String country
                String state
            }

An item can have either a Person or a Place associated with it, but not both. I want to query a list of Items based on if their Address matches either an associated Person or Place's address by searching against country AND state. My current implementation looks something like this:

            public static Specification<Item> locationIs(String country, String state) {
                return (root, query, criteriaBuilder) -> {
                    Expression<String> personCountry = root.get("person").get("address").get("country");
                    Expression<String> placeCountry = root.get("place").get("address").get("country");
                    Expression<String> personState = root.get("person").get("address").get("state");
                    Expression<String> placeState = root.get("place").get("address").get("state");

                    Predicate personCountryMatch = criteriaBuilder.like(personCountry, "%"   country   "%");
                    Predicate personStateMatch = criteriaBuilder.like(personState, "%"   state   "%");
                    Predicate personMatch = criteriaBuilder.and(personCountryMatch, personStateMatch);

                    Predicate placeCountryMatch = criteriaBuilder.like(placeCountry, "%"   country   "%");
                    Predicate placeStateMatch = criteriaBuilder.like(placeState, "%"   state   "%");
                    Predicate placeMatch = criteriaBuilder.and(placeCountryMatch, placeStateMatch);

                    Predicate match = criteriaBuilder.or(personMatch, placeMatch);

                    return match
                };
            }

If I return just personMatch or just placeMatch it appears to work perfectly for searching on that, but as soon as I try to or them together the whole query returns no results. I've tried creating Specifications from each predicate and combining them that way using , same result.

CodePudding user response:

Ended up just using subqueries for this instead, did something like

criteriaBuilder.or(criteriaBuilder.exists(subquery1), criteriaBuilder.exists(subquery2))

And that worked fine

CodePudding user response:

While subqueries can be a good alternative, the query you seemed to be aiming for originally would have been:

Join<Person> person = root.join("person", JoinType.LEFT);
Join<Person> place = root.join("place", JoinType.LEFT);

Predicate personCountryMatch = criteriaBuilder.like(person.get("country"), "%"   country   "%");
Predicate personStateMatch = criteriaBuilder.like(person.get("state"), "%"   state   "%");
Predicate personMatch = criteriaBuilder.and(personCountryMatch, personStateMatch);

Predicate placeCountryMatch = criteriaBuilder.like(place.get("country"), "%"   country   "%");
Predicate placeStateMatch = criteriaBuilder.like(lace.get("state"), "%"   state   "%");
Predicate placeMatch = criteriaBuilder.and(placeCountryMatch, placeStateMatch);

Predicate match = criteriaBuilder.or(personMatch, placeMatch);

return match
  • Related