Search code examples
collectionsjdodatanucleustransient

Datanucleus Query: accessing transient collection after close


I have a specific query method in all my managers that must return a transient collection, but i want to CLOSE the query immediately after executing it.

tx.begin();
Query query=pm.newQuery(...);
Collection col=(Collection)query.execute();
pm.makeTransientAll(col,true);
query.close();
tx.commit();

The problem: The collection CANNOT be accessed after the query is closed (DN knows the identity?) otherwise it throws a "Query has been closed" error!

The solution: Create a COPY of the original collection!

Collection col=new ArrayList((Collection)query.execute());

But i want to avoid that... Even if it's a local copy and it's not a deep clone, it still allocates the space needed for the entire array of elements (so, at some point there is going to be 2x allocated memory) and i would like to avoid that.

I'm i missing something? Is there a way to avoid the creation of a clone?


Solution

  • Well, i found the reason of this behavior:

    The query Object returned (collection) if an instance of: org.datanucleus.store.rdbms.query.ForwardQueryResult
    that extends: AbstractRDBMSQueryResult
    that extends: AbstractQueryResult
    that extends: AbstractList

    so, i get an object that is a LIST implementation, and the query result is bound to that implementation.

    /** The Result Objects. */
    protected List resultObjs = new ArrayList();
    
    /**
     * Method to return the results as an array.
     * @return The array.
     */
    public synchronized Object[] toArray()
    {
        assertIsOpen();
        advanceToEndOfResultSet();
    
        return resultObjs.toArray();
    }
    

    So, i cannot avoid the creation of a NEW array...