3

У меня есть метод, который переопределяет метод «toPredicate»:Как использовать javax.persistence.criteria.Predicate со сложными типами?

@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; 

} 

С помощью этого простого класса я могу сделать:

@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; 

} 

Что я должен делать, если я хочу сделать предикат с комплексным атрибутом «документы»?

Я пробовал:

@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) 

Моя задача состоит в том, чтобы найти каждый человек с детерминированным видом документа. Как я могу это сделать?

Спасибо.

ответ

5

вы можете использовать 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); 

     } 
+0

Хорошо, спасибо за предложить. Кажется, что это работает, но все еще есть проблема. Если я делаю: predicates.add (cb.equal (root.join («документы»). Get («type»), type)); он возвращает все документы с определенным типом, поэтому я могу иметь дубликаты результатов для класса Person. Пример: «Джек» У человека есть три документа, из которых 2 имеют тип = «Бумага». С этой реализацией у меня есть 2 записи типа «Person» (оба являются «Jack») –

+0

@AlessandroC взгляните на мое редактирование –

+0

cq.distinct (true); кажется, достаточно, cq.select (root) дает мне ошибку компиляции. Однако, спасибо за вашу помощь! –

Смежные вопросы