Я пытаюсь получить данные от родителя к потомку на основе критериев фильтрации с использованием запроса критериев JPA, чтобы можно было избежать множественных запросов к БД, но не смог достичь желаемого результата. Ниже приведены мои образцы сущностей (без геттеров / сеттеров)
@Entity
public class ParentTable implements Serializable{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "ID")
private String id;
@Column(name = "KEY_COLUMN",length = 30)
private String keyColumn;
@Column(name = "CODE",length = 30)
private String code;
@Column(name = "KEY_DESC",length = 240)
private String desc;
@OneToMany(mappedBy = "parentTable",cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<ChildTable> childTableList;
}
@Entity
public class ChildTable implements Serializable{
private static final long serialVersionUID = 1L;
public ChildTable() {
super();
}
@Id
@Column(name = "ID",length = 80)
private String id;
@Column(name = "PARENT_KEY_COLUMN",length = 30,insertable = false,updatable = false)
private String parentKeyColumn;
@Column(name = "CHILD_CODE",length = 30)
private String childCode;
@Column(name = "CHILD_DESC",length = 240)
private String chldDesc;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "PARENT_KEY_COLUMN", referencedColumnName = "KEY_COLUMN")
private ParentTable parentTable;
}
Фрагмент построителя критериев -
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<ParentTable> query = cb.createQuery(ParentTable.class);
Root<ParentTable> fromParent = query.from(ParentTable.class);
Join<ParentTable, ChildTable> details = fromParent.join("childTableList");
List<Predicate> conditions = new ArrayList();
conditions.add(cb.equal(details.get("childCode"), childCode));
conditions.add(cb.equal(details.get("chldDesc"),chldDesc));
TypedQuery<ParentTable> typedQuery = em.createQuery(query.select(fromParent).where(conditions.toArray(new Predicate[] {})));
List<ParentTable> parentTableList = typedQuery.getResultList();
Это выполняется и дает результат только для родительской таблицы, если я получаю данные дочерней таблицы, я могу увидеть, что запрос JPA снова исключается, можно ли этого избежать и получить список дочерних объектов, который соответствует 3 параметрам динамического c? 1. ParentTable.code, 2. ChildTable.childCode, 3. ChildTable.chldDes c.
Может ли кто-нибудь помочь мне построить запрос JPA, как показано ниже, который выполняется в одном обращении к базе данных вместо нескольких циклов приема-передачи, что происходит в приведенном выше фрагменте кода?
select * from ParentTable p,ChildTable c where p.KEY_COLUMN=c.PARENT_KEY_COLUMN and p.CODE=? and c.CHILD_CODE=? and c.CHILD_DESC=?
Обновление:
CriteriaBuilder builder = entityManager.getCriteriaBuilder();
CriteriaQuery<ParentTable> cq = builder.createQuery(ParentTable.class);
Root<ParentTable> root = cq.from(ParentTable.class);
Join<ParentTable, ChildTable> join = root.join("childTableList");
Predicate p1=builder.equal(root.get("code"), "code");
Predicate p2=builder.like(join.get("chldDesc"), "%chldDesc%");
Predicate p3=builder.equal(join.get("childCode"), "childCode");
Predicate andPredicate = builder.and(p1,p2, p3);
cq.select(root).where(andPredicate);
EntityGraph<ParentTable> fetchGraph = entityManager.createEntityGraph(ParentTable.class);
fetchGraph.addSubgraph("childTableList");
List<ParentTable> parentTableList=entityManager.createQuery(cq).setHint("javax.persistence.loadgraph", fetchGraph).getResultList();
parentTableList.forEach(System.out::println);
Этот подход формирует ожидаемый запрос, как указано выше, но снова формируется еще один запрос, как показано ниже, почему запускается второй запрос даже если это не требуется?
select * from ParentTable parentTable0_ where parentTable0_.code=?