How to join fetch only selected children entities with parent entity

Ognjen Mišić :

I'm trying to select only certain entities alongside the parent by ids. Is this possible? Example (boilerplate omitted):

class Parent {
   int id;
   List<Child> children;
}

class Child {
   int id;
   ...
}

And my JpaRepository:

interface ParentRepo extends JpaRepo<Parent,Integer> {
    @Query("SELECT p FROM Parent p JOIN p.children c WHERE p.id = :parentId and c.id IN(:childIds")
    Parent getParentByIdAndChildIds(int parentId, List<Integer> childIds)
}

My expectation is that calling:

parentRepo.getParentByIdAndChildIds(1, Arrays.asList(1,2,3))

will return the parent object with only 3 child entities attached, but instead, I get ALL of the children (i.e. children with ids from 1-10).

Andronicus :

That wouldn't make any sense, because the whole entity graph needs to be fetched. Consider a parent p having children c1, c2 and c3 and only ids of c1 and c2 are passed to your method. If you fetch a Parent entity with c1 and c2 only, then what happens, if you do something like this:

p = parentRepo.getParentByIdAndChildIds(1, Arrays.asList(1,2));
p.getChildren().add(c3);
parentRepo.save(p); // what happens?

Creating a new child does not make sense, because there already exists one in the database. On the other hand the default behavior of jpa would delete relationship between p and c3 when saved without modifying:

p = parentRepo.getParentByIdAndChildIds(1, Arrays.asList(1,2));
parentRepo.save(p); // is the relationship between p and c3 destroyed

Consider creating a bidirectional relationship (also from Child to Parent) and fetching the Child entities only (from ChildRepository):

interface ChildRepository extends JpaRepository<Child, Integer> {
    @Query("SELECT c FROM Child c WHERE c.parent.id = :parentId and c.id IN(:childIds)")
    List<Child> getParentByIdAndChildIds(int parentId, List<Integer> childIds)
}

That way you only get the Child entities you want, but also Parent is reachable from any Child (children.get(0).getParent()).

Guess you like

Origin http://10.200.1.11:23101/article/api/json?id=374727&siteId=1