2015-04-17 95 views
5

我正在用queryDsl進行查詢。在Oracle 11上使用queryDsl獲取兩天之間天差的問題

我用它來創建一個BooleanExpresion

public BooleanBuilder getPredicate(BooleanBuilder pBuilderBusquePerso){ 

int dias = 30; 

QEntity1 qEntity = QEntity1.entity; 

pBuilderBusquePerso = pBuilderBusquePerso.and(qEntity.date1 != null 
? (SQLExpressions.datediff(DatePart.day, qEntity.date2, qEntity.date1).lt(dias)) :null); 

return pBuilderBusquePerso; 
} 

而在另一個程序我打電話,然後執行此爲:

BooleanBuilder pBuilderBusquePerso = new BooleanBuilder(); 

Predicate filter =getPredicate(pBuilderBusquePerso); 

Page<Entity> iLista = myRepository.findAll(getMyPredicate(usr, filter, tipoListado, null, estados), paginacion); 

所以SQL查詢的結果是:

select table1 ta1 
...... 
exists (
select 1 
from 
table2 ta2 
where 
    ta1.inv_id=ta2.inv_id 
and diff_days(ta1.inv_exp_date, ta2.exp_date)<? 
) 

給出以下錯誤:

Caused by: java.sql.SQLException: ORA-00904: "DIFF_DAYS": invalid identifier

所以ddbb oracle的querysql翻譯是錯誤的。有沒有辦法將queryDsl翻譯成oracle函數?我需要什麼?

我也試圖與DATETRUNC

pBuilderBusquePerso = pBuilderBusquePerso.and(qEntity.date1 != null 
? (SQLExpressions.datetrunc(DatePart.day, qEntity.date1).castToNum(Integer.class).subtract(SQLExpressions.datetrunc(DatePart.day, qEntity.date2).castToNum(Integer.class))).lt(dias) :null); 




exists (
select 1 
from 
table2 ta2 
where 
    ta1.inv_id=ta2.inv_id 
    and cast(trunc_day(ta2.exp_date) as number(10,0))-cast(trunc_day(ta1.inv_exp_date) as number(10,0))<? 

給人一種類似的錯誤:

Caused by: java.sql.SQLException: ORA-00904: "TRUNC_DAY": invalid identifier

而且addDays

pBuilderBusquePerso = pBuilderBusquePerso.and(qEntity.date1 != null 
? ((SQLExpressions.addDays(qEntity.date2, dias)).after(qEntity.date1)):null); 


exists (
select 1 
from 
table2 ta2 
where 
    ta1.inv_id=ta2.inv_id 
    and add_days(ta1.inv_exp_date, ?)>ta1.exp_date 
) 

給予另一個類似的錯誤:

Caused by: java.sql.SQLException: ORA-00904: "ADD_DAYS": invalid identifier

我試圖按照這個測試來構建我的查詢 https://searchcode.com/codesearch/view/17765673/

在此先感謝。

編輯:這是完整的錯誤跟蹤。

org.springframework.dao.InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.convertHibernateAccessException(HibernateJpaDialect.java:231) 
    at org.springframework.orm.jpa.vendor.HibernateJpaDialect.translateExceptionIfPossible(HibernateJpaDialect.java:214) 
    at org.springframework.orm.jpa.AbstractEntityManagerFactoryBean.translateExceptionIfPossible(AbstractEntityManagerFactoryBean.java:417) 
    at org.springframework.dao.support.ChainedPersistenceExceptionTranslator.translateExceptionIfPossible(ChainedPersistenceExceptionTranslator.java:59) 
    at org.springframework.dao.support.DataAccessUtils.translateIfNecessary(DataAccessUtils.java:213) 
..................... 


...................... 
Caused by: org.hibernate.exception.SQLGrammarException: could not extract ResultSet 
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:123) 
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125) 
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110) 

...................... 
...................... 
...................... 

(And here comes the ORA error) 

Caused by: java.sql.SQLException: ORA-00904: "TRUNC_DAY": invalid identifier 

    at oracle.jdbc.driver.DatabaseError.throwSqlException(DatabaseError.java:112) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:331) 
    at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:288) 

..... 
+0

oracle中沒有這些函數。 – OldProgrammer

+0

那麼我知道,因爲它在oracle sql developer中試過查詢。但有沒有辦法將queryDsl表達式轉換爲oracle函數? – Vic

+0

你可能會說DATE1-DATE2這樣的天數差異 – Randy

回答

0

根據評論,這在Oracle中是不可能的。不過,由於您已標記javaJoda-Time非常適合計算兩個日期之間的差異。

public int CalculateDifference(DateTime date1, DateTime date2) { 
    return Days.daysBetween(date1, date2).getDays(); 
} 
+0

我知道,但是,有沒有辦法使用QueryDsl的Joda-Time?,我的問題是嘗試將queryDsl謂詞與SQLExpresions功能一起使用到Oracle中。 – Vic

1

SQLExpressions方法與SQL一起使用時,不使用JPA/JPQL查詢纔有效。 Querydsl JPA不提供開箱即用的,因爲JPA不支持它。

+2

因此,對於Querydsl,兩個日期之間的差異將會是什麼樣的解決方案?或者爲日期添加日期並將其與queryDsl中的其他日期進行比較? – Vic

0

最後,我們只是改變了焦點來解決問題後,意識到這是不可能做的queryDsl,所以我們創建一個自定義存儲庫,然後我們執行一個查詢來獲得天,所以我們從ID獲取一個表,然後我們使用它們來過濾使用querydsl進行的其他查詢的結果。

我希望這會有所幫助。

@Repository 
 
public class MyRepositoryImpl implements MyRepository, InitializingBean { 
 

 
\t @PersistenceContext 
 
\t private EntityManager em; 
 

 
\t private QTable1 qTable1; 
 
\t private PathBuilder<Table1> path; 
 
\t private Querydsl querydsl; 
 
\t private JPASQLQuery sqlquery; 
 
\t private SQLTemplates templates; 
 

 
\t @Override 
 
\t public void afterPropertiesSet() throws Exception { 
 
\t \t this.qTable1 = QTable1.table1; 
 
\t \t this.path = new PathBuilder<Table1>(qTable1.getType(), qTable1.getMetadata()); 
 
\t \t this.querydsl = new Querydsl(em, path); 
 

 
\t \t this.templates = new OracleTemplates(); 
 
\t \t this.sqlquery = new JPASQLQuery(em, templates); 
 
\t } 
 

 

 

 

 

 
\t @Override 
 
\t public List<Long> findDiasFecha(String data1, int id) { 
 

 
\t \t String myQuery =null; 
 
\t \t int dias; 
 

 
\t \t switch (id) { 
 
\t  \t case 1: dias = 30; 
 
\t  \t \t \t break; 
 
\t   case 2: dias = 60; 
 
\t   \t \t break; 
 
\t   case 3: dias = 90; 
 
\t   \t \t break; 
 
\t   case 4: dias = 120; 
 
\t \t \t \t \t break; 
 
\t \t \t \t \t \t //5 & 6 are for 180 days 
 
\t   default: dias = 180; 
 
\t   \t \t break; 
 
\t \t } 
 

 
\t \t 
 
\t \t \t myQuery =" SELECT i1.invId FROM Table1 i1 WHERE i1.invRecCif = :data1 and "+ 
 
\t \t \t \t \t " i1.invId IN "+ 
 
\t \t \t \t \t " (SELECT i2.invId "+ 
 
\t \t \t \t \t " FROM Table1 i2, "+ 
 
\t \t \t \t \t "  Table2 pd "+ 
 
\t \t \t \t \t " WHERE pd.entrada.invId = i2.invId "+ 
 
\t \t \t \t \t " and i1.invId = i2.invId "+ 
 
\t \t \t \t \t " AND TRUNC(pd.expDate)-TRUNC(i2.invExpDate)<= :dias "+ 
 
\t \t \t \t \t " )"; 
 
\t \t 
 

 
\t \t Long diasL = new Long(dias); 
 
\t \t TypedQuery<Long> typedQuery = em.createQuery(myQuery , Long.class); 
 
\t \t typedQuery.setParameter("dias", (double) diasL); 
 
\t \t typedQuery.setParameter("data1", data1); 
 

 
\t \t List<Long> results = typedQuery.getResultList(); 
 

 
\t \t return results; 
 
\t \t } 
 

 

 
\t 
 

 
}

0

不可能的JPQL,因爲缺乏日期計算的。但它可以通過使用JPASQLQuery與OracleTemplates本機查詢來完成,請參見:http://www.querydsl.com/static/querydsl/latest/reference/html_single/#d0e431

final JPASQLQuery query = new JPASQLQuery(em, OracleTemplates.DEFAULT); 
//without jpa use: com.querydsl.sql.oracle.OracleQuery 
query.select(
     SQLExpressions.datediff(
      DatePart.day, 
      SQLExpressions.datetrunc(DatePart.day, qEntity.date1), 
      SQLExpressions.datetrunc(DatePart.day, qEntity.date2))) 
     .from(qEntity); 
0

我決定這個所以...

protected enum TypeCompare { 
           EQ, 
           GT, 
           GOE, 
           LT, 
           LOE 
    } 
    private final static String ORACLE_DATE_FORMAT = "dd.mm.yyyy"; 

...

protected BooleanExpression dateCompare(DateTimePath<java.util.Date> dateTimePath, Date date, TypeCompare typeCompare) { 
     StringTemplate dbDate = Expressions.stringTemplate("function('TRUNC', {0})", dateTimePath); 
     StringTemplate compareDate = Expressions.stringTemplate("function('TO_DATE', {0}, {1})", DateUtils.formatRuDate(date), ORACLE_DATE_FORMAT); 
     switch (typeCompare) { 
      case EQ: 
       return dbDate.eq(compareDate); 
      case GT: 
       return dbDate.gt(compareDate); 
      case GOE: 
       return dbDate.goe(compareDate); 
      case LT: 
       return dbDate.lt(compareDate); 
      case LOE: 
       return dbDate.loe(compareDate); 
      default: 
       return dbDate.eq(compareDate); 
     } 
    } 

QueryDSL JPA Functions