2016-08-19 83 views
3

我正在研究基於QueryDSL並使用SpringData進行查詢執行的動態過濾器組件。因此,我從收到的數據廣告中將Predicate個實例創建爲QueryDslPredicateExecutor。對於動態訪問實體屬性,我使用類型爲實體類的通用PathBuilder通過其元素的多個屬性過濾器集合 - QueryDSL

考慮以下(簡化)代碼:

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

當我嘗試查詢Offer entites的,那些在他們的收藏name與屬性「ABC」元素,我簡單地創建謂詞如下:

pathBuilder.getCollection("names", LanguageToName.class).any().getString("name") 
    .like("%" + fieldData.getFieldValue() + "%"); 

但是,我無法想出一個解決方案,使用PathBuilder通過包含對象的多個屬性過濾集合。當我將上面的代碼附加到.and()並通過pathBuilder變量再次訪問集合時,我自然會得到相當於將AND EXISTS...附加到sql查詢的結果,這不是所需的結果。我也嘗試使用getCollection().contains(),但我無法創建描述這種情況的Expression<LanguageToName>

有沒有辦法創建一個Predicate可以通過集合中元素的多個屬性過濾實體,即查詢實體的字段?

回答

0

我在我的項目中遇到了同樣的問題。 我的解決方法是手動構建存在的子查詢。

假設你的兩個類被映射爲實體:

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

與任何(一個簡單的查詢):

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

映射到

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=? 
    ) 

子查詢:

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

映射到:

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=? 
    ) 

其以前的完美匹配的SQL。 您可以添加附加條件,如:

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