Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 393
Zdend Avatar asked Aug 20 '12 11:08

Zdend


People also ask

What is JPA spring data specification?

SPring Data Jpa Specifications helps us to create dynamic queries based on the requirement at run time. Spring Data Jpa Specifications allows a combination of the attributes or properties of a domain or entity class and creates a query.

How can I join JPA specification?

Joining Tables with JPA Specifications select author0_.id as id1_1_, author0_. first_name as first_na2_1_, author0_. last_name as last_nam3_1_ from author author0_ inner join author_books books1_ on author0_.id = books1_. author_id inner join book book2_ on books1_.

What is @OneToMany in spring boot?

The @OneToMany annotation is from the java persistence API specification. This annotation represents that a collection of objects are direct children of the current entity. So let us see how this annotation works. For this, We are going to use the same entities from our previous @ManyToOne example.

How do you join unrelated entities with JPA and Hibernate?

The only way to join two unrelated entities with JPA 2.1 and Hibernate versions older than 5.1, is to create a cross join and reduce the cartesian product in the WHERE statement. This is harder to read and does not support outer joins. Hibernate 5.1 introduced explicit joins on unrelated entities.


2 Answers

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);
            }
        };
    }
like image 159
Zdend Avatar answered Oct 22 '22 20:10

Zdend


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.

like image 27
CodeChimp Avatar answered Oct 22 '22 21:10

CodeChimp