复合键的 JPQL 异常
Posted
技术标签:
【中文标题】复合键的 JPQL 异常【英文标题】:JPQL Exception for composite key 【发布时间】:2013-06-16 10:54:49 【问题描述】:我无法知道 2 JPQL 异常的解决方案
-
子查询必须只返回一列字段
[PARENTENTITY.PARENTID2]
在这个表达式中有一个无效的表
这个语境
对于以下实体--
class ParentEntity
@Id
String parentId1;
@Id
String parentId2;
@ManyToOne
ChildEntity childEntityRef;
class ChildEntity
@Id
String childId1;
@Id
String childId2;
当我尝试查询时 -
SELECT me.childId1,me.childId2 FROM ChildEntity as me where me <> ALL(Select pe.childEntityRef From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
它给出了以下异常-
Caused by: Exception [EclipseLink-6069] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.QueryException
Exception Description: The field [PARENTENTITY.PARENTID2] in this expression has an invalid table in this context.
at org.eclipse.persistence.exceptions.QueryException.invalidTableForFieldInExpression(QueryException.java:712)
at org.eclipse.persistence.internal.expressions.FieldExpression.validateNode(FieldExpression.java:277)
at org.eclipse.persistence.expressions.Expression.normalize(Expression.java:2978)
at org.eclipse.persistence.internal.expressions.DataExpression.normalize(DataExpression.java:342)
at org.eclipse.persistence.internal.expressions.FieldExpression.normalize(FieldExpression.java:205)
at org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:218)
当我尝试查询时 -
SELECT me.childId1,me.childId2 FROM ChildEntity as me where me <> (Select pe.childEntityRef From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
它给出了以下异常-
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.3.0.v20110604-r9504): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: subquery must return only one column
Error Code: 0
Call: SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE ( <> (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2 LEFT OUTER JOIN CHILDENTITY t1 ON ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1)) WHERE ((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?))))
bind => [2 parameters bound]
Query: ReportQuery(referenceClass=ChildEntity sql="SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE ( <> (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2 LEFT OUTER JOIN CHILDENTITY t1 ON ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1)) WHERE ((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?))))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:333)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:644)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.executeCall(DatabaseAccessor.java:535)
Caused by: org.postgresql.util.PSQLException: ERROR: subquery must return only one column
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1592)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1327)
【问题讨论】:
【参考方案1】:尝试使用 2.4 或 2.5 版本,有很多 JPQL 增强和修复。尽管您尝试做的事情我仍然无法按照您尝试的方式进行。
尝试简化您的查询,
SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exists (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef = me)
或者,
SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exists (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef.childId1 = me.childId1 and pe.childEntityRef.childId2 = me.childId2)
在 2.5 中你应该也可以做到,
SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1, mew.childId2) NOT IN (Select pe.childEntityRef.childId1, pe.childEntityRef.childId2 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
【讨论】:
【参考方案2】:詹姆斯,请澄清下面定义的异常(响应您描述的查询)... 使用 Eclipselink 2.5 版本 [eclipselink-2.5.0.v20130507-3faac2b]
JPA 查询 1) SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exist (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef = me)
输出-
Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exist (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef = me)], line 1, column 70: unexpected token [(].
Internal Exception: NoViableAltException(81!=[652:1: simpleConditionalExpressionRemainder[Object left] returns [Object node] : (n= comparisonExpression[left] | (n1= NOT )? n= conditionWithNotExpression[(n1!=null), left] | IS (n2= NOT )? n= isExpression[(n2!=null), left] );])
at org.eclipse.persistence.exceptions.JPQLException.unexpectedToken(JPQLException.java:372)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.handleRecognitionException(JPQLParser.java:319)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.addError(JPQLParser.java:245)
JPA 查询 2) SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exist (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef.childId1 = me.childId1 and pe.childEntityRef.childId2 = me.childId2)
输出-
Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT me.childId1,me.childId2 FROM ChildEntity as me where not exist (Select pe.parentId1 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 and pe.childEntityRef.childId1 = me.childId1 and pe.childEntityRef.childId2 = me.childId2)], line 1, column 70: unexpected token [(].
Internal Exception: NoViableAltException(81!=[652:1: simpleConditionalExpressionRemainder[Object left] returns [Object node] : (n= comparisonExpression[left] | (n1= NOT )? n= conditionWithNotExpression[(n1!=null), left] | IS (n2= NOT )? n= isExpression[(n2!=null), left] );])
at org.eclipse.persistence.exceptions.JPQLException.unexpectedToken(JPQLException.java:372)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.handleRecognitionException(JPQLParser.java:319)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.addError(JPQLParser.java:245)
JPA 查询 3) SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1,me.childId2) NOT IN (Select pe.childEntityRef.childId1, pe.childEntityRef.childId2 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
输出-
Caused by: Exception [EclipseLink-8024] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1,me.childId2) NOT IN (Select pe.childEntityRef.childId1, pe.childEntityRef.childId2 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )], line 1, column 72: syntax error at [,].
Internal Exception: MismatchedTokenException(79!=82)
at org.eclipse.persistence.exceptions.JPQLException.syntaxErrorAt(JPQLException.java:362)
at org.eclipse.persistence.internal.jpa.parsing.jpql.JPQLParser.handleRecognitionException(JPQLParser.java:304)
但 PostgreSQL 查询运行良好:
SQL 查询 1)
SELECT me.childId1,me.childId2 FROM ChildEntity as me where NOT EXISTS (
Select pe.parentId1 From ParentEntity as pe where pe.parentId1=? and pe.parentId2=?
and pe.childId1 = me.childId1 and pe.childId2 = me.childId2)
SQL 查询 2)
SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1,me.childId2) NOT IN (
Select pe.childId1, pe.childId2 From ParentEntity as pe where pe.parentId1=? and pe.parentId2=?)
更新:
对于第三个 JPA 查询)SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1,me.childId2) NOT IN (Select pe.childEntityRef.childId1, pe.childEntityRef.childId2 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
输出-
[EL Warning]: 2013-06-18 19:21:54.407--UnitOfWork(15545028)--Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: invalid reference to FROM-clause entry for table "childentity"
Error Code: 0
Exception in thread "main" javax.persistence.PersistenceException: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Call: SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))
Internal Exception: org.postgresql.util.PSQLException: ERROR: invalid reference to FROM-clause entry for table "childentity"
bind => [2 parameters bound]
Error Code: 0
Query: ReportQuery(referenceClass=ChildEntity sql="SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))")
Call: SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))
bind => [2 parameters bound]
Query: ReportQuery(referenceClass=ChildEntity sql="SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))")
at org.eclipse.persistence.internal.jpa.QueryImpl.getDetailedException(QueryImpl.java:377)
at org.eclipse.persistence.internal.jpa.QueryImpl.executeReadQuery(QueryImpl.java:260)
at org.eclipse.persistence.internal.jpa.QueryImpl.getResultList(QueryImpl.java:468)
at com.NewClass.main(NewClass.java:27)
Caused by: Exception [EclipseLink-4002] (Eclipse Persistence Services - 2.5.0.v20130507-3faac2b): org.eclipse.persistence.exceptions.DatabaseException
Internal Exception: org.postgresql.util.PSQLException: ERROR: invalid reference to FROM-clause entry for table "childentity"
Error Code: 0
Call: SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))
bind => [2 parameters bound]
Query: ReportQuery(referenceClass=ChildEntity sql="SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))")
at org.eclipse.persistence.exceptions.DatabaseException.sqlException(DatabaseException.java:340)
at org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor.basicExecuteCall(DatabaseAccessor.java:679)
Caused by: org.postgresql.util.PSQLException: ERROR: invalid reference to FROM-clause entry for table "childentity"
at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:1592)
at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1327)
Postgresql 查询)SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTITY.CHILDID1, CHILDENTITY.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))
输出-
ERROR: invalid reference to FROM-clause entry for table "childentity"
LINE 3: ....CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (CHILDENTIT...
^
HINT: Perhaps you meant to reference the table alias "t0".
********** Error **********
ERROR: invalid reference to FROM-clause entry for table "childentity"
SQL state: 42P01
Hint: Perhaps you meant to reference the table alias "t0".
Character: 62
更新的 Postgresql 查询)——别名 CHILDENTITY 被 t0 替换,然后完美运行 -
SELECT t0.CHILDID1, t0.CHILDID2 FROM CHILDENTITY t0 WHERE (t0.CHILDID1, t0.CHILDID2) NOT IN (SELECT t1.CHILDID1, t1.CHILDID2 FROM PARENTENTITY t2, CHILDENTITY t1 WHERE (((t2.PARENTID1 = ?) AND (t2.PARENTID2 = ?)) AND ((t1.CHILDID2 = t2.CHILDID2) AND (t1.CHILDID1 = t2.CHILDID1))))
【讨论】:
好吧,首先,您使用的是 2.0.1.v20100213-r6600 作为错误状态,而不是您所说的 2.5... 另外,我有个错字,是 EXISTS 不是 EXIST 1 和 2 查询现在都可以正常工作(因为 EXISTS not EXIST) 第三个 JPA 查询SELECT me.childId1,me.childId2 FROM ChildEntity as me where (me.childId1,me.childId2) NOT IN (Select pe.childEntityRef.childId1, pe.childEntityRef.childId2 From ParentEntity as pe where pe.parentId1=:parentId1 and pe.parentId2=:parentId2 )
(在 Eclipselink 2.5 中支持)由于 本机 sql 查询中的别名问题而无法正常工作。是 eclipselink 2.5 中的错误还是 JPA Query 中的任何问题。以上是关于复合键的 JPQL 异常的主要内容,如果未能解决你的问题,请参考以下文章
使用 Spring-data-cassandra 查询具有复合主键的表
使用Spring-data-cassandra查询具有复合主键的表