3

Ich habe eine Methode, die die Methode „toPredicate“ überschreibt:Wie verwendet man javax.persistence.criteria.Predicate mit komplexen Typen?

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

ich die Prädikate zu bauen. Es ist einfach, mit einfachen Typen, zum Beispiel:

@Entity 
@Table 
public class Person { 

    @Column 
    private String name; 

    @Column 
    private String surname; 

} 

Mit dieser einfachen Klasse kann ich tun:

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

Aber wenn das Attribut ein komplexer Typ ist, wie kann ich das einfache Attribut finden enthielt in der komplexe Typ?

Dies ist eine mögliche Situation:

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

} 

Was muss ich tun, wenn ich ein Prädikat mit dem komplexen Attribut „Dokumente“ machen?

Ich habe versucht:

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

Aber ich habe diese Ausnahme:

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) 

Meine Aufgabe ist es, jede Person mit einer bestimmten Art von Dokument zu finden. Wie kann ich es tun?

Danke.

Antwort

5

können Sie join verwenden:

@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

Ok, danke für die vorschlagen. Es scheint zu funktionieren, aber es gibt immer noch ein Problem. Wenn ich Folgendes mache: Prädikate.add (cb.equal (root.join ("Dokumente"). Get ("Typ"), Typ)); Es gibt alle Dokumente mit einem bestimmten Typ zurück, sodass ich doppelte Ergebnisse für die Klasse Person erhalten kann. Ein Beispiel: "Jack" Person hat drei Dokumente, von denen 2 Typ = "Papier" haben. Mit dieser Implementierung habe ich 2 Datensätze vom Typ "Person" (beide sind "Jack") –

+0

@AlessandroC werfen Sie einen Blick auf meine Bearbeitung –

+0

cq.distinct (true); scheint genug zu sein, cq.select (root) gib mir einen Kompilierungsfehler. Vielen Dank für Ihre Hilfe! –

Verwandte Themen