Search code examples
javahibernateentityjpa-criteria

Is there a way to return Specifications for Parent Entity for org.springframework.data.jpa.domain.Specification?


Suppose I have a bidirectional 1-1 association with the Person entity

@Entity
public class Person {
  @OneToOne(optional=false)
  @JoinColumn(name = "contact_id")
  private Contact contact;


  // getters/setters/constructors
}

And the Contact Entity

@Entity
public class Contact {
  @OneToOne(mappedBy="contact")
  private Person person;

  // getters/setters/
}

I couldn't find a way to select parent object for Person Entity using the Contact entity. Like so...

criteriaQuery.select(root.get(Contact_.person));

I get this error:

Incompatible types. Required Selection<? extends capture of ?> but 'get' was inferred to Path<Y>: no instance(s) of type variable(s) exist so that Person conforms to capture of ?

Is there a way of doing this? I wanted to return a Predicate for Person Entity using the Contact root. For eg.

public static Specification<Person> phoneWithCountryCode(String countryCode) {
    return new Specification<Person>() {
        @Override
        public Predicate toPredicate(
            Root<Contact> root,
            CriteriaQuery<?> criteriaQuery,
            CriteriaBuilder criteriaBuilder
        ) {
            String startsWithPattern = countryCode + "%";
            criteriaQuery.select(root.get(Contact_.person));
            return criteriaBuilder.like(
                root.get(Contact_.phone), startsWithPattern
            );
        }
    };
}

Solution

  • Yes, you can do. I did it.I Have Relationship ( Book -- Review).

    In your case create Specification<Person> and use join with contact. like this,

    Join joins = root.join("contact");
    

    If help requires just follow my code.

    public class BookSpecification {
    
        public static Specification<Book> getBookByNameAndReviewId(){
    
            return new Specification<Book> () {
    
                @Override
                public Predicate toPredicate(Root<Book> root, CriteriaQuery<?> query, CriteriaBuilder cb) 
                {
                 //List<javax.persistence.criteria.Predicate>
                List<Predicate> predicates = new ArrayList<>();
                predicates.add(cb.equal(root.get("name"), "spring boot"));
                Join joins = root.join("reviews");
                predicates.add(cb.equal(joins.get("no") , 584));
    
                    return cb.and(predicates.toArray(new Predicate[predicates.size()]));
                // return cb.equal(root, predicates);
                }
    
            };
        }
    }