如何对复杂类型使用 javax.persistence.criteria.Predicate?

How to use javax.persistence.criteria.Predicate with complex types?

我有一个覆盖方法 "toPredicate":

的方法
@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    List<Predicate> predicates = new ArrayList<>();

我必须构建谓词。 使用简单类型很容易,例如:

@Entity
@Table
public class Person {

    @Column
    private String name;

    @Column
    private String surname;

}

有了这个简单的 class 我可以做到:

@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    List<Predicate> predicates = new ArrayList<>();

    if (StringUtils.isNotBlank(surname)) {
        predicates.add(cb.equal(root.get("surname"), surname));
    }

    if (StringUtils.isNotBlank(name)) {
        predicates.add(cb.equal(root.get("name"), name));
    }

但是如果属性是复杂类型,如何找到复杂类型中包含的简单属性呢?

这是一个潜在的情况:

@Entity
@Table
public class Person {

    @Column
    private String name;

    @Column
    private String surname;

    @OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
    private List<Document> documents;

}

@Entity
@Table
public class Document {

    @Column
    private String type;

    @Column
    private String code;

}

想做一个复杂属性的谓词怎么办"documents"?

我试过了:

@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    List<Predicate> predicates = new ArrayList<>();

    if (StringUtils.isNotBlank(type)) {
        predicates.add(cb.equal(root.get("documents").get("type"), type));
    }

但是我有这个例外:

java.lang.IllegalStateException: Illegal attempt to dereference path source [null.documents] of basic type
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.illegalDereference(AbstractPathImpl.java:98)
    at org.hibernate.jpa.criteria.path.AbstractPathImpl.get(AbstractPathImpl.java:191)

我的任务是找到每个具有确定类型文档的人。 我该怎么做?

谢谢。

您可以使用 join:

@Override
public Predicate toPredicate(Root<Person> root, CriteriaQuery<?> cq, CriteriaBuilder cb) {
    Predicate predicate = null;

    if (StringUtils.isNotBlank(type)) {
        predicate = cb.equal(root.join("documents").get("type"), type);

       cq.where(predicate);
       cq.distinct(true);

      }