[
Date Prev][
Date Next][
Thread Prev][
Thread Next][
Date Index][
Thread Index]
[
List Home]
[eclipselink-users] bug? criteria query, "invalid query key in expression"
|
Hello,
A criteria query which used to work in 2.2.0 doesn't anymore in 2.3.2.
Sorry, it's quite long. Basically, a Subscription has a Client. I need
to find clients who had multiple valid supscriptions between a start and
an end date.
Here is the criteria query:
Date minSimultaneousSubscriptionDate =
clientSearch.getMinSimultaneousSubscriptionDate();
Date maxSimultaneousSubscriptionDate =
clientSearch.getMaxSimultaneousSubscriptionDate();
if (minSimultaneousSubscriptionDate != null ||
maxSimultaneousSubscriptionDate != null) {
// subquery 1: subscription begins between given dates
Subquery firstSubscriptionSubquery =
criteriaQuery.subquery(Subscription.class);
Root<Subscription> firstSubscriptionRoot =
firstSubscriptionSubquery.from(Subscription.class);
List<Predicate> firstSubscriptionPredicates = new
ArrayList<Predicate>();
// client for subquery 1
Path<Client> firstSubscriptionClientPath =
firstSubscriptionRoot.get(Subscription_.client);
Predicate firstSubscriptionClientPredicate =
builder.equal(firstSubscriptionClientPath, clientRoot);
firstSubscriptionPredicates.add(firstSubscriptionClientPredicate);
// start / end dates
List<Predicate> firstSubscriptionDatePredicates =
createSubscriptionAtDatePredicates(firstSubscriptionRoot,
minSimultaneousSubscriptionDate, maxSimultaneousSubscriptionDate);
firstSubscriptionPredicates.addAll(firstSubscriptionDatePredicates );
// subquery 2: second subscription overlapping first
Subquery secondSubscriptionSubquery =
criteriaQuery.subquery(Subscription.class);
Root<Subscription> secondSubscriptionRoot =
secondSubscriptionSubquery.from(Subscription.class);
// client for second subscription
List<Predicate> secondSubscriptionPredicates = new
ArrayList<Predicate>();
Path<Client> secondSubscriptionClientPath =
secondSubscriptionRoot.get(Subscription_.client);
Predicate secondSubscriptionClientPredicate =
builder.equal(secondSubscriptionClientPath, clientRoot);
secondSubscriptionPredicates.add(secondSubscriptionClientPredicate);
// subscriptions of both subqueries must be different
Predicate firstAndSecondSubscriptionDifferentPredicates =
builder.notEqual(secondSubscriptionRoot, firstSubscriptionRoot);
secondSubscriptionPredicates.add(firstAndSecondSubscriptionDifferentPredicates);
// subscription dates of subscription 2 shoud overlap those
of subscription 1
Path<Date> firstSubscriptionStartDatePath =
firstSubscriptionRoot.get(Subscription_.startDate);
Path<Date> firstSubscriptionEffectiveEndDatePath =
firstSubscriptionRoot.get(Subscription_.effectiveEndDate);
Path<Date> secondSubscriptionStartDatePath =
secondSubscriptionRoot.get(Subscription_.startDate);
Path<Date> secondSubscriptionEffectiveEndDatePath =
secondSubscriptionRoot.get(Subscription_.effectiveEndDate);
Predicate firstSubscriptionNoEndDatePredicate =
builder.isNull(firstSubscriptionEffectiveEndDatePath);
Predicate secondSubscriptionNoEndDatePredicate =
builder.isNull(secondSubscriptionEffectiveEndDatePath);
Predicate secondSubscriptionStartsBeforeFirstEndsPredicate
= builder.lessThan(secondSubscriptionStartDatePath,
firstSubscriptionEffectiveEndDatePath);
Predicate secondSubscriptionEndsAfterFirstStartsPredicate =
builder.greaterThan(secondSubscriptionEffectiveEndDatePath,
firstSubscriptionStartDatePath);
Predicate secondSubscriptionStartPredicate =
builder.or(firstSubscriptionNoEndDatePredicate,
secondSubscriptionStartsBeforeFirstEndsPredicate);
Predicate secondSubscriptionEndPredicate =
builder.or(secondSubscriptionNoEndDatePredicate,
secondSubscriptionEndsAfterFirstStartsPredicate);
secondSubscriptionPredicates.add(secondSubscriptionStartPredicate);
secondSubscriptionPredicates.add(secondSubscriptionEndPredicate);
Predicate[] secondSubscriptionPredicateArray =
secondSubscriptionPredicates.toArray(new Predicate[0]);
secondSubscriptionSubquery.where(secondSubscriptionPredicateArray);
// subscription 2 exists for subscription 1
Predicate secondSubscriptionExistsPredicate =
builder.exists(secondSubscriptionSubquery);
firstSubscriptionPredicates.add(secondSubscriptionExistsPredicate);
Predicate[] firstSubscriptionPredicateArray =
firstSubscriptionPredicates.toArray(new Predicate[0]);
firstSubscriptionSubquery.where(firstSubscriptionPredicateArray);
// subscription 1 exists for client
Predicate firstSubscriptionExistsPredicate =
builder.exists(firstSubscriptionSubquery);
predicates.add(firstSubscriptionExistsPredicate);
}
Here is the sql generated in 2.2.0:
SELECT ... FROM subscription t0, client t1 WHERE (EXISTS (SELECT ? FROM
subscription t2 WHERE ((((t2.CLIENT_ID = t1.ID) AND
(t2.SUBSCRIPTION_START_DATE <= ?)) AND ((t2.effective_end_date IS NULL)
OR (t2.effective_end_date > ?))) AND EXISTS (SELECT ? FROM subscription
t3 WHERE ((((t3.CLIENT_ID = t1.ID) AND NOT ((t2.ID = t3.ID))) AND
((t2.effective_end_date IS NULL) OR (t3.SUBSCRIPTION_START_DATE <
t2.effective_end_date))) AND ((t3.effective_end_date IS NULL) OR
(t3.effective_end_date > t2.SUBSCRIPTION_START_DATE)))) )) AND (t0.ID =
t1.SUBSCRIPTION_ID)) ORDER BY t1.ID DESC LIMIT ?, ?
bind => [1, 2012-05-01 00:00:00.0, 2012-04-01, 1, 0, 50]|#]
Here is the error I get in 2.3.2:
Exception [EclipseLink-6015] (Eclipse Persistence Services -
2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.QueryException
Exception Description: Invalid query key [effectiveEndDate] in expression.
Query: ReportQuery(referenceClass=Client )
at
org.eclipse.persistence.exceptions.QueryException.invalidQueryKeyInExpression(QueryException.java:670)
at
org.eclipse.persistence.internal.expressions.QueryKeyExpression.validateNode(QueryKeyExpression.java:851)
at
org.eclipse.persistence.internal.expressions.FunctionExpression.normalize(FunctionExpression.java:392)
at
org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:218)
at
org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:226)
at
org.eclipse.persistence.internal.expressions.CompoundExpression.normalize(CompoundExpression.java:218)
at
org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1300)
at
org.eclipse.persistence.internal.expressions.SubSelectExpression.normalizeSubSelect(SubSelectExpression.java:197)
at
org.eclipse.persistence.internal.expressions.ExpressionNormalizer.normalizeSubSelects(ExpressionNormalizer.java:93)
at
org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1373)
at
org.eclipse.persistence.internal.expressions.SubSelectExpression.normalizeSubSelect(SubSelectExpression.java:197)
at
org.eclipse.persistence.internal.expressions.ExpressionNormalizer.normalizeSubSelects(ExpressionNormalizer.java:93)
at
org.eclipse.persistence.internal.expressions.SQLSelectStatement.normalize(SQLSelectStatement.java:1373)
at
org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:586)
at
org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.buildReportQuerySelectStatement(ExpressionQueryMechanism.java:531)
at
org.eclipse.persistence.internal.queries.ExpressionQueryMechanism.prepareReportQuerySelectAllRows(ExpressionQueryMechanism.java:1590)
at
org.eclipse.persistence.queries.ReportQuery.prepareSelectAllRows(ReportQuery.java:1296)
at
org.eclipse.persistence.queries.ReadAllQuery.prepare(ReadAllQuery.java:644)
at
org.eclipse.persistence.queries.ReportQuery.prepare(ReportQuery.java:1056)
at
org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:613)
at
org.eclipse.persistence.queries.ObjectLevelReadQuery.checkPrepare(ObjectLevelReadQuery.java:823)
at
org.eclipse.persistence.queries.DatabaseQuery.checkPrepare(DatabaseQuery.java:575)
at
org.eclipse.persistence.queries.DatabaseQuery.execute(DatabaseQuery.java:812)
at
org.eclipse.persistence.queries.ObjectLevelReadQuery.execute(ObjectLevelReadQuery.java:1040)
at
org.eclipse.persistence.queries.ReadAllQuery.execute(ReadAllQuery.java:392)
at
org.eclipse.persistence.queries.ObjectLevelReadQuery.executeInUnitOfWork(ObjectLevelReadQuery.java:1128)
at
org.eclipse.persistence.internal.sessions.UnitOfWorkImpl.internalExecuteQuery(UnitOfWorkImpl.java:2871)
at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1516)
at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1498)
at
org.eclipse.persistence.internal.sessions.AbstractSession.executeQuery(AbstractSession.java:1463)
at
org.eclipse.persistence.internal.jpa.EJBQueryImpl.executeReadQuery(EJBQueryImpl.java:485)
at
org.eclipse.persistence.internal.jpa.EJBQueryImpl.getSingleResult(EJBQueryImpl.java:773)
at [my classes]
If I remove all correlating predicates, and put the "exists" predicate
on the client query instead of the first subscription subquery, it
doesn't complain and executes corresponding sql. Any correlation between
the two subqueries, and it goes wrong.
Best regards,
Yannick Majoros