jdodatanucleusjdoql

Ordering using a declared variable's property


I have a ScInfo class that exists in many different classes. This class also has a list of ScDetails which has a Date member variable called nextExecution.

I need to continuously look up eligible objects with their ScDetails object's nextExecution member variable is after or equal to the current server's time (i.e. persistenceManagerInstance.getServerDate()). Meaning that I need to look up objects, with ScInfo having a ScDetails object with nextExecution >= serverDate)

So I use the following method (A portion is shown):

public List<Object[]> getEligbleForExecution(long amount) {
    PersistenceManager pm = null;
    Transaction t = null;
    try {
        pm = getPM();
        t = pm.currentTransaction();
        t.begin();
        Query q = pm
                .newQuery(
                        entityClass, //This is generic
                        "!this.deleted && this.scheduleActive && det.active == true && (det.nextExecution == null || det.nextExecution <= :serverDate) && det.running == false && this.scInfo.scDetails.contains(det)");
        q.declareVariables(ScDetail.class.getName() + " det;");
        q.setRange(0, amount);
        q.setResult("this, det");
        q.setOrdering("det.nextExecution"); // This is the statement I need to apply but it's causing the error below
        Date serverDate = pm.getServerDate();
        List<Object[]> raw = new ArrayList<Object[]>((List<Object[]>) q.execute(serverDate));

Which throws the following error stack trace (DEBUG level, I mentioned what I thought to be essential for solving this problem):

14:54:32 DEBUG (Log4JLogger.java:58)-[main] >> QueryToSQL.processVariable (unbound) variable=det is not yet bound so returning UnboundExpression
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Updating mapping of org.datanucleus.store.rdbms.sql.expression.NullLiteral@727f3b8a to be org.datanucleus.store.mapped.mapping.DateMapping@e72a8082
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Transaction rolling back for ObjectManager org.datanucleus.MultithreadedObjectManager@fba0f36
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Rolling back [DataNucleus Transaction, ID=Xid={A strange uncopyable character is in here !}, enlisted resources=[]]
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Transaction rolled back in 1 ms
14:54:32 ERROR (ScTasksDAOImpl.java:67)-[main] Looking up eligible SC tasks
java.lang.NullPointerException
    at org.datanucleus.store.rdbms.query.QueryToSQLMapper.processVariableExpression(QueryToSQLMapper.java:3245)
    at org.datanucleus.store.rdbms.query.QueryToSQLMapper.processPrimaryExpression(QueryToSQLMapper.java:2075)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compilePrimaryExpression(AbstractExpressionEvaluator.java:180)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileUnaryExpression(AbstractExpressionEvaluator.java:169)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileAdditiveMultiplicativeExpression(AbstractExpressionEvaluator.java:148)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileRelationalExpression(AbstractExpressionEvaluator.java:123)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.compileOrAndExpression(AbstractExpressionEvaluator.java:65)
    at org.datanucleus.query.evaluator.AbstractExpressionEvaluator.evaluate(AbstractExpressionEvaluator.java:46)
    at org.datanucleus.query.expression.Expression.evaluate(Expression.java:337)
    at org.datanucleus.store.rdbms.query.QueryToSQLMapper.compileOrdering(QueryToSQLMapper.java:845)
    at org.datanucleus.store.rdbms.query.QueryToSQLMapper.compile(QueryToSQLMapper.java:403)
    at org.datanucleus.store.rdbms.query.JDOQLQuery.compileQueryFull(JDOQLQuery.java:883)
    at org.datanucleus.store.rdbms.query.JDOQLQuery.compileInternal(JDOQLQuery.java:343)
    at org.datanucleus.store.query.Query.executeQuery(Query.java:1747)
    at org.datanucleus.store.query.Query.executeWithArray(Query.java:1666)
    at org.datanucleus.api.jdo.JDOQuery.execute(JDOQuery.java:243)
    at com.sc.ipk.sc.services.ScTasksDAOImpl.getEligbleForExecution(ScTasksDAOImpl.java:41)
    at com.sc.ipk.ixl.services.IxlTestDAOImpl.main(IxlTestDAOImpl.java:977)
14:54:32 DEBUG (Log4JLogger.java:58)-[main] Object Manager "org.datanucleus.MultithreadedObjectManager@fba0f36" closed

So is it not possible to use declared variables to query ordering ? I tried using sub-queries but I couldn't get that to work either, may be I can start a new question for that, if ordering using declared variables isn't possible.

EDIT: Neil generously suggested that ordering based on an element that should exist in a collection doesn't look reasonable to him. I understand that but I cannot for example look-up ScDetails objects first after ordering them of course and then look-up my main objects afterwards because my target main object may differ from time to time and I may look-up ScDetails objects that doesn't belong to the main candidate class.

For example: A has ScInfo which has a collection of ScDetails B, C (Same as above)

So if I lookup ScDetails objects first (After ordering an all), I cannot filter my main candidate classes (A, B & C) because I may use a ScDetails that belongs to A while I'm trying to get B or C candidates.

Thank you.


Solution

  • I don't see how you can order by that variable. It represents an element of a collection of the candidate. Consequently if a candidate has say 5 elements then it is indeterminate how it can order by some property on the element (1-N mapping). Obviously if the candidate was the element then ordering by some property of the element makes perfect sense, whether variable or not.