2013-05-30 39 views
1

我創建了一個靜態方法的類,它返回Querydsl的BooleanExpressions,所以我可以簡單地將這些表達式傳遞給我的Spring Data存儲庫中的findAll()findOne()方法,並在整個應用程序中重用它們。像這樣:http://www.petrikainulainen.net/programming/spring-framework/spring-data-jpa-tutorial-part-five-querydsl/優化Querydsl BooleanExpression查詢

是我遇到的問題是,多數民衆贊成正從我的方法返回的BooleanExpression爲生成似乎是次優的(至少對我的情況)查詢。

方法返回二進制表達式的值:

public static BooleanExpression byExternalIdAndProviderId(
    final String externalId, final Long providerId) { 

    QEListing listing = QEListing.eListing; 

    return listing.externalIds.any().externalId.equalsIgnoreCase(externalId) 
     .and(listing.externalIds.any().provider.id.eq(providerId)); 
} 

查詢時產生:

select elisting0_.id as id1_24_, 
    elisting0_.address1 as address2_24_, 
    elisting0_.address2 as address3_24_, 
    elisting0_.business_name as business4_24_, 
    elisting0_.city_id as city10_24_, 
    elisting0_.created_date as created5_24_, 
    elisting0_.latitude as latitude6_24_, 
    elisting0_.longitude as longitud7_24_, 
    elisting0_.master_ext_id as master11_24_, 
    elisting0_.modified_date as modified8_24_, 
    elisting0_.state_id as state12_24_, 
    elisting0_.zip as zip13_24_, 
    elisting0_.zip_4 as zip9_24_, 
    elisting0_1_.vanity_name as vanity1_34_, 
    elisting0_2_.account_id as account1_2_ 
from listings elisting0_ 
    left outer join vanity_names elisting0_1_ on elisting0_.id=elisting0_1_.listing_id 
    left outer join accounts_to_listings elisting0_2_ on elisting0_.id=elisting0_2_.listing_id 
where (
    exists (
     select 1 
     from external_ids eexternali1_ 
     where (
      eexternali1_.id in (
       select externalid2_.external_id 
       from listing_to_external_id externalid2_ 
       where elisting0_.id=externalid2_.listing_id)) 
       and lower(eexternali1_.external_id)='123456' 
     ) 
    ) 
and (
    exists (
     select 1 
     from external_ids eexternali3_ 
     where (
      eexternali3_.id in (
       select externalid4_.external_id 
       from listing_to_external_id externalid4_ 
       where elisting0_.id=externalid4_.listing_id 
      ) 
     ) 
     and eexternali3_.provider_id=1 
    ) 
) 

至於反對這樣的事情:

select elisting0_.id as id1_24_, 
    elisting0_.address1 as address2_24_, 
    elisting0_.address2 as address3_24_, 
    elisting0_.business_name as business4_24_, 
    elisting0_.city_id as city10_24_, 
    elisting0_.created_date as created5_24_, 
    elisting0_.latitude as latitude6_24_, 
    elisting0_.longitude as longitud7_24_, 
    elisting0_.master_ext_id as master11_24_, 
    elisting0_.modified_date as modified8_24_, 
    elisting0_.state_id as state12_24_, 
    elisting0_.zip as zip13_24_, 
    elisting0_.zip_4 as zip9_24_, 
    elisting0_1_.vanity_name as vanity1_34_, 
    elisting0_2_.account_id as account1_2_ 
from listings elisting0_ 
    left outer join vanity_names elisting0_1_ on elisting0_.id=elisting0_1_.listing_id 
    left outer join accounts_to_listings elisting0_2_ on elisting0_.id=elisting0_2_.listing_id 
    join listing_to_external_id a on elisting0_.id = a.listing_id 
    join external_ids b on a.external_id = b.id 
where lower(b.external_id) = '123456' 
and b.provider_id = 1 

有什麼辦法來產生更優化的查詢,同時仍然提供了BooleanExpressions的可重用性,並且還使用了Spring D. ata的倉庫?

回答

1

有可能是一個更好的方法,但連接無法使用,因爲它們修改的結果集。因此,如果您找到一種方法來優化Querydsl中的any()子查詢,那麼請在GitHub問題跟蹤器中創建一個票據。

當Querydsl使用僅限於斷言,那麼有沒有控制權的連接。

+0

從我發現,使用Querydsl與Spring數據的唯一途徑是通過傳遞謂詞擴展'QueryDslPredicateExecutor '庫。我非常喜歡使用Querydsl,但這些查詢對我來說是個問題。除了謂詞之外,還有沒有其他方式可以像Spring那樣使用Spring Data和Querydsl?當你說連接修改結果集時,是否意味着它們會改變返回的列,這取決於你是否選擇了所有字段,甚至是連接表中的那些字段? – Luke

+0

加入不修改返回哪些列,但許多行如何匹配,從而改變尋呼參數,如限制和抵消。 findAll方法是簡單查詢個案的簡便方法。另一種方法是使用完整的Querydsl查詢。 –

+0

對,所以我想找回實體管理器是春季使用的數據和它傳遞給一個'新JPAQuery()'在2.1.5節,在這裏:http://www.querydsl.com/static/querydsl /2.9.0/reference/html/ch02.html#d0e185。我跟隨? – Luke