2014-07-12 69 views
0

我有一個CriteriaQuery中:JPA的EclipseLink Oracle數據庫缺少右括號

CriteriaQuery<Employee> criteriaQuery = criteriaBuilder.createQuery(Employee.class); 
Root<Employee> root = criteriaQuery.from(Employee.class); 
criteriaQuery.where(criteriaBuilder.equal(root.get("type"), 1)); 

然後從現有的查詢構建rowCount時查詢:

CriteriaQuery<Long> countQuery = criteriaBuilder.createQuery(Long.class); 
    Root<Employee> root = criteriaQuery.from(Employee.class); 
    Predicate restriction = criteriaQuery.getRestriction(); 
    if (restriction != null) 
     countQuery.where(restriction); 

    countQuery.select(criteriaBuilder.countDistinct(root)); 

從調試,

Predicate restriction = criteriaQuery.getRestriction(); 

CriteriaQuery中。從調試器看到的是(TYPE =?)。 上面返回的限制不是(TYPE =?),而是((TYPE =?)=?)。

Eclipse中生成的SQL:

SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?) 

導致上的Oracle 11g數據庫錯誤。

Error Code: 907 
    Call: SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?) 
      bind => [1, true] 
    Query: ReportQuery(referenceClass=Employee.class sql="SELECT COUNT(DISTINCT(ID)) FROM EMPLOYEE WHERE ((TYPE = ?) = ?)") 
00:31:24,718 ERROR [system] ORA-00907: missing right parenthesis 

java.sql.SQLSyntaxErrorException: ORA-00907: missing right parenthesis 

     at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:447) 
     at oracle.jdbc.driver.T4CTTIoer.processError(T4CTTIoer.java:396) 
     at oracle.jdbc.driver.T4C8Oall.processError(T4C8Oall.java:951) 
     at oracle.jdbc.driver.T4CTTIfun.receive(T4CTTIfun.java:513) 
     at oracle.jdbc.driver.T4CTTIfun.doRPC(T4CTTIfun.java:227) 
     at oracle.jdbc.driver.T4C8Oall.doOALL(T4C8Oall.java:531) 
     at oracle.jdbc.driver.T4CPreparedStatement.doOall8(T4CPreparedStatement.java:208) 
     at oracle.jdbc.driver.T4CPreparedStatement.executeForDescribe(T4CPreparedStatement.java:886) 
     at oracle.jdbc.driver.OracleStatement.executeMaybeDescribe(OracleStatement.java:1175) 
     at oracle.jdbc.driver.OracleStatement.doExecuteWithTimeout(OracleStatement.java:1296) 
     at oracle.jdbc.driver.OraclePreparedStatement.executeInternal(OraclePreparedStatement.java:3613) 
     at oracle.jdbc.driver.OraclePreparedStatement.executeQuery(OraclePreparedStatement.java:3657) 
     at oracle.jdbc.driver.OraclePreparedStatementWrapper.executeQuery(OraclePreparedStatementWrapper.java:1495) 
     at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeSelect(DatabaseAccessor.java:1007) 
     at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:642) 
     at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:558) 
     at org.eclipse.persistence.internal.sessions.AbstractSession.basicExecuteCall(AbstractSession.java:1991) 
     at org.eclipse.persistence.sessions.server.ServerSession.executeCall(ServerSession.java:570) 
     at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:242) 
     at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeCall(DatasourceCallQueryMechanism.java:228) 
     at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.executeSelectCall(DatasourceCallQueryMechanism.java:299) 
     at org.eclipse.persistence.internal.queries.DatasourceCallQueryMechanism.selectAllRows(DatasourceCallQueryMechanism.java:694) 
     at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllRowsFromTable(ExpressionQueryMechanism.java:2738) 
     at org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.selectAllReportQueryRows(ExpressionQueryMechanism.java:2675) 
     at org.eclipse.persistence.queries.ReportQuery.executeDatabaseQuery(ReportQuery.java:848) 
     at org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:899) 
     at org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1127) 
     at org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:403) 
     at org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1215) 
     at org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2896) 
     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1793) 
     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1775) 
     at org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1740) 
     at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:258) 
     at org.eclipse.persistence.internal.jpa.QueryImpl.getSingleResult(QueryImpl.java:517) 
     at org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:400) 

生成((TYPE =?)=?)而不是(TYPE =?)的原因是什麼?

感謝您的任何幫助。

+0

我在Oracle 11g上使用EclipseLink 2.5.1。 – Dave

回答

0

不太瞭解綁定的「TYPE」的實際值,看起來被綁定的實際值內嵌入的單引號可能會導致此錯誤。

從以下站點引述解釋這一點:ORA-00907: missing right parenthesis tips

如果您在由其他單引號的短語用單引號,則必須由內單引號添加另一個單引號,以避免ORA-00907。例如,你必須使用「'「」 」爲了ORA-00907在語法不被拆毀‘’」代替。

*編輯1

想想也看你的類型參數的靜態元模型表示。例如:

ParameterExpression<String> typeParam = criteriaBuilder.parameter(Integer.class); 

criteriaQuery.where(criteriaBuilder.equal(root.get(Employee_.type), typeParam)); 

其中Employee_type是由JPA規範定義的靜態元模型。

下面是使用舊版EclipseLink的一個示例。因人而異:

JPA 2.0 Criteria API with Maven and EclipseLink

+0

更新了問題,並找到問題。還沒有想出如何解決它。謝謝。 – Dave

+0

有沒有辦法剝離((TYPE = 1)= true)成爲(TYPE = 1)或阻止(TYPE = 1)被封裝爲((TYPE = 1)= true)? – Dave

+0

你可以發佈你的員工實體嗎?不知道它是如何被註釋的,會影響內部生成SQL的方式。 – Rai

0

您不能重複使用謂詞/因爲它們依賴於綁定在特定查詢的特定CriteriaBuilder查詢之間的限制。 EclipseLink允許重用構建的查詢,但在進行更改之前,您必須訪問本機API並克隆基礎EclipseLink查詢。

+0

我喜歡遠離本機API。如果加上虛擬1 = 1,即(TYPE =?)和(1 = 1),它就起作用。有沒有辦法來判斷一個限制是否是至少兩個布爾表達式的連接(AND)?如果爲false,則添加虛擬(1 = 1)。 – Dave

+0

如果您不嘗試執行計數查詢,原始查詢是否工作? – Chris

+0

原始查詢工作。但使用criteriaQuery.getRestriction()逐步構建查詢並添加新謂詞將失敗 – Dave