Zdend
Zdend

Reputation: 611

Spring data JPA Specifications - @OneToMany dependency

i have a problem with getting List from entity Person using Spring data JPA specifications (because of pagination). I need to get all notes by person but dependency between these two entities is on Person side. I don't know how to create my Predicate because Note doesn't contain any attribute related to Person.

I simply can get List with Persons getter but i can't use this way because i need returned data paginated.

@Entity
public class Person implements Serializable {

    @Id
    private Long personId;

    @OneToMany
    @JoinColumn(name = "personId")
    private List<Note> notes;

}

@Entity
public class Note implements Serializable {

    @Id
    private Long noteId;
}

Normally, I would write something like this, but i don't have an attribute person in Note and database can't be remapped at this stage.

public static Specification<Note> notesByPerson(final Long personId) {
        return new Specification<Note>() {
            @Override
            public Predicate toPredicate(final Root<Note> root, final CriteriaQuery<?> query,
                    final CriteriaBuilder builder) {

                final Path<Person> per = root.<Person> get("person");

                return builder.equal(per.<Long> get("personId"), personId);

            }
        };
    }

Thank you, Zdend

Upvotes: 9

Views: 19742

Answers (2)

Zdend
Zdend

Reputation: 611

Solved..

public static Specification<Note> notesByPerson(final Long personId) {
        return new Specification<Note>() {

            @Override
            public Predicate toPredicate(final Root<Note> noteRoot, final CriteriaQuery<?> query,
                    final CriteriaBuilder cb) {

                final Subquery<Long> personQuery = query.subquery(Long.class);
                final Root<Person> person = personQuery.from(Person.class);
                final Join<Person, Note> notes = person.join("notes");
                personQuery.select(notes.<Long> get("noteId"));
                personQuery.where(cb.equal(person.<Long> get("personId"), personId));

                return cb.in(noteRoot.get("noteId")).value(personQuery);
            }
        };
    }

Upvotes: 13

CodeChimp
CodeChimp

Reputation: 8154

I am not sure how to do that with Predicates, as I usually dont use them, but in JPQL (or HQL, which is similar), you can do something like this:

SELECT Note n FROM Person.notes WHERE XXXX

It is basically the same thing as doing this in SQL

SELECT n.noteId FROM person as p JOIN persons_notes pn ON pn.person=p.personId JOIN notes as n ON n.noteId=pn.noteId

I would venture a guess that the Predicate method has similar abilities as described above.

Upvotes: 1

Related Questions