2016-02-19 49 views
0

我需要優化動態查詢。這樣的例子,但它有更多的過濾器(BooleanExpression)Union subselects querydsl

QTable qtable = QTable.table; 

BooleanExpression pSubQueryFilter = qtable.field4.in(List<Long>).and((date != null) ? qtable.field5.goe(date) : null); 

BooleanExpression pSubQuery =(((qtable.field1.eq(string1)) .and(qtable .field2.eq(string2)).and(qtable .field3.eq(Boolean.FALSE))) 
.or((qtable.field1.eq(string2)).and(qtable .field2.eq(string1).and(qtable .field3.eq(Boolean.TRUE)))) 
).and(pSubQueryFilter); 

List<T> list = createQuery(pSubQuery).list(path); 

這會產生這種選擇,但是花費超過30s中的DB或因條款。該字段(field1和field2)已經在數據庫中進行了索引。

SELECT * FROM table WHERE 

    (field1= 'string1' AND field2='string2' AND field3=0) 

    OR (field1= 'string2' AND field2='string1' AND field3=1) 

    AND field4 in (1,2,3,4,5,...) AND field5 > =SYSDATE-365 

    ORDER BY field5 DESC, id DESC 

我這個優化選擇,以1秒的SQL這個結果:

SELECT * FROM table WHERE 

    id IN ((SELECT id FROM table WHERE field1= 'string1' AND field2='string2' AND field3=0) 

    UNION (SELECT id FROM table WHERE field1= 'string2' AND field2='string1' AND field3=1)) 

    AND field4 in (1,2,3,4,5,...) AND field5 > =SYSDATE-365 

    ORDER BY field5 DESC, id DESC 

但QueryDsl沒有得到改善。我這樣做,因爲聯盟沒有工作。

BooleanExpression psubq1 = qtable .field1.eq(string1).and(qtable .field2.eq(string2)).and(qtable .field3.eq(Boolean.FALSE)); 

BooleanExpression psubq2 = qtable .field1.eq(string2).and(qtable .field2.eq(string1)).and(qtable .field3.eq(Boolean.TRUE)); 

Expression<?>[] args = { qtable .id}; 

List<Long> resultids = tableRepository.findAllIds(psubq1, args); 

resultids.addAll(tableRepository.findAllIds(psubq2, args)); 

pSubQuery = qtable .id.in(resultids).and(pSubQueryFilter); 

是否存在任何方式通過一次調用DB來執行帶有Querydsl的最後一個sql?

謝謝

回答

0

存在一個靜態方法unioncom.querydsl.sql.SQLExpressions做到這一點。由於參數使用使用SQLExpressions::select創建的子查詢。

import com.querydsl.core.types.dsl.*; 
import com.querydsl.sql.DatePart; 
import com.querydsl.sql.SQLExpressions; 
import com.querydsl.sql.oracle.OracleGrammar; 
import com.querydsl.sql.oracle.OracleQuery; 
... 
OracleQuery query = new OracleQuery<>(con); 
query.select(table).from(table).where(
    table.id.in(
     SQLExpressions.union(
      SQLExpressions.select(table.id).from(table) 
       .where(table.field1.eq("string1") 
        .and(table.field2.eq("string2")) 
        .and(table.field3.eq(Expressions.FALSE))), 
      SQLExpressions.select(table.id) 
       .from(table) 
       .where(table.field1.eq("string2") 
        .and(table.field2.eq("string1")) 
        .and(table.field3.eq(Expressions.TRUE)))) 
    ) 
    .and(table.field4.in(1,2,3,4,5)) 
    .and(table.field5.goe(
     SQLExpressions.dateadd(DatePart.day, OracleGrammar.sysdate, -365)))) 
.orderBy(table.field5.desc(), table.id.desc());;