我有两个实体 A 和 B,其中 A 是父实体,B 是子实体。我想使用 JPA 规范(如规范)来过滤记录。
它们的关系是实体 B 引用 A。我想使用 JPA Criteria Builder API 在实体 A 上应用左连接。有可能实现吗?
这是我的 Parent 实体类
@Entity
public class Parent {
@Id
private Long parentId;
private String name;
private String description;
// constructor, getter and setters
}
这是我的子实体类
@Entity
public class Child {
@Id
private Long childId;
private String childName;
private String email;
@ManyToOne
@JoinColumn(name = "parent_id")
private Parent parent;
// constructor, getter and setters
}
我想实现类似下面的代码,只是想根据父规范中子实体的
childName
过滤每条记录。
@Component
public class ParentSpecification {
public Specification<Parent> getParentSpecification(Map<String, String> filterValues) {
return (root, query, criteriaBuilder) -> {
Root<Child> from = query.from(Child.class);
from.join("parent", JoinType.LEFT);
List<Predicate> predicates = new ArrayList<>();
filterValues.forEach((attribute, value) -> {
if (attribute.equalsIgnoreCase("childName") && value != null) {
predicates.add(criteriaBuilder.like(from.get("childName"), "%" + value + "%"));
}
});
return query.where(criteriaBuilder.and(predicates.toArray(new Predicate[0]))).getRestriction();
};
}
}
网上有很多关于这个主题的资源。
示例:
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Tuple> cq = cb.createTupleQuery();
Root<Author> root = cq.from(Author.class);
Join<Object, Object> book = root.join(Author_.BOOKS, JoinType.LEFT);
cq.multiselect(root, book);
ParameterExpression<String> pLastName = cb.parameter(String.class);
cq.where(cb.equal(root.get(Author_.LAST_NAME), pLastName));
TypedQuery<Tuple> q = em.createQuery(cq);
q.setParameter(pLastName, "Janssen");
List<Tuple> authorBooks = q.getResultList();
@Ritesh - 你有没有得到任何解决方案。我也陷入使用 JPA 规范/分页的类似场景。