2016-08-19 11 views
3

Ich arbeite an einer dynamischen Filterkomponente basierend auf QueryDSL mit der Verwendung von SpringData für die Abfrageausführung. So erstelle ich Predicate Instanzen von der empfangenen Datenanzeige übergeben Sie es an QueryDslPredicateExecutor. Für den dynamischen Zugriff auf Entitätsattribute verwende ich den generischen Code PathBuilder, der in die Entitätsklasse eingegeben wurde.Filtern der Sammlung nach mehreren Attributen seiner Elemente - QueryDSL

Betrachten Sie die folgende (vereinfachte) Code:

class Offer { 
    List<LanguageToName> names; 
} 
class LanguageToName { 
    String name; 
    String language; 
} 

Wenn ich versuche, Offer entites abzufragen, die in ihrer Sammlung name Element mit dem Attribut 'abc' haben, habe ich einfach das Prädikat wie folgt erstellen:

Ich konnte jedoch keine Lösung finden, um die Sammlung nach mehreren Attributen der enthaltenen Objekte mit PathBuilder zu filtern. Wenn ich den Code oben mit .and() anhänge und die Sammlung wieder über die Variable pathBuilder zugreife, bekomme ich natürlich das Ergebnis, das dem Anfügen der sql Abfrage mit AND EXISTS... entspricht, das nicht das erwünschte Resultat ist. Ich versuchte auch, getCollection().contains() zu verwenden, aber ich war nicht in der Lage, die Expression<LanguageToName> zu schaffen, die solchen Fall beschreiben würde.

Gibt es eine Möglichkeit, eine Predicate zu erstellen, die Entitäten nach mehreren Attributen der Elemente aus einer Auflistung filtern würde, also ein Feld der abgefragten Entität?

Antwort

0

Ich lief über das gleiche Problem in meinem Projekt. Meine Problemumgehung besteht darin, die Exis-Unterabfrage manuell zu erstellen.

vorausgesetzt, dass Ihre beide Klassen werden als Entitäten abgebildet:

@Entity 
@Table(name = "Offer") 
public class Offer { 

    @Id 
    String id; 

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "offer") 
    List<LanguageToName> names; 
} 

@Entity 
@Table(schema = "dcsdba", name = "Language_To_Name") 
public class LanguageToName { 

    @Id 
    String id; 

    @ManyToOne(fetch= FetchType.LAZY) 
    @JoinColumn(name="Offer_id") 
    private Offer offer; 

    String name; 
    String language; 
} 

Eine einfache Abfrage mit jedem():

BooleanExpression namesFilter = QOffer.offer.names.any().name.eq("Esperanto"); 

Karten

select 
    offer0_.id as id1_7_ 
from 
    offer offer0_ 
where 
    exists (
     select 
      1 
     from 
      dcsdba.language_to_name names1_ 
     where 
      offer0_.id=names1_.offer_id 
      and names1_.name=? 
    ) 

einer Unterabfrage:

BooleanExpression namesFilter = JPAExpressions.selectOne() 
      .from(languageToName) 
      .where(languageToName.offer.eq(QOffer.offer) 
        .and(languageToName.name.eq("Esperanto"))) 
      .exists(); 

Maps:

select 
    offer0_.id as id1_7_ 
from 
    offer offer0_ 
where 
    exists (
     select 
      1 
     from 
      dcsdba.language_to_name languageto1_ 
     where 
      languageto1_.offer_id=offer0_.id 
      and languageto1_.name=? 
    ) 

die perfekt vorherige SQL entspricht. Sie können weitere Bedingungen hinzufügen wie:

BooleanExpression namesFilter = JPAExpressions.selectOne() 
      .from(languageToName) 
      .where(languageToName.offer.eq(QOffer.offer) 
        .and(languageToName.name.eq("Esperanto")) 
        .and(languageToName.language.like("E%"))) 
      .exists(); 
Verwandte Themen