Jay
Jay

Reputation: 20169

How do you make query results available after closing the persistence manager

I am learning GAE and am getting a bit stuck. If I use the following, with a finally to make sure the persistence manager is closed, I get an exception when trying to actually read the Note objects:

public class Notes {
    public List<Note> getAll() {
    PersistenceManager pm = PMF.instance().getPersistenceManager();

    try {
        Query query = pm.newQuery("select from com.uptecs.google1.model.Note order by subject");
        return (List<Note>) query.execute();
    } finally {
        pm.close();
    }
    }
}

The exception I get is this:

Object Manager has been closed
org.datanucleus.exceptions.NucleusUserException: Object Manager has been closed
    at org.datanucleus.ObjectManagerImpl.assertIsOpen(ObjectManagerImpl.java:3876)
    at org.datanucleus.ObjectManagerImpl.getFetchPlan(ObjectManagerImpl.java:376)
    at org.datanucleus.store.query.Query.getFetchPlan(Query.java:497)

Upvotes: 5

Views: 3174

Answers (3)

Ga&#235;l Oberson
Ga&#235;l Oberson

Reputation: 603

In addition to the answer from bakkal, I would say that you absolutely need the detachable="true" annotation parameter, otherwise you will never get it to work. To detach a list of objects, you can also use pm.detachCopyAll(your_query_result_list), wich will be a bit faster than your implementation of the iteration to detach, and will let you spare a few lines of code. Thanks JDO ! ;-) But be aware, this method requires explicit cast of its results.

Here's a working example I currently use in my last App (the Key used in the query is an Encoded String) :

pm = PMF.get().getPersistenceManager();

Query query = pm.newQuery(TandemSubscription.class);
query.setFilter("groupSubscriptionKey==groupSubscriptionKeyParam");
query.setOrdering("dateRDV desc");
query.declareParameters("String groupSubscriptionKeyParam");

// Get Data
@SuppressWarnings("unchecked")          
List<TandemSubscription> savedSubscriptions = 
     (List<TandemSubscription>) query.execute(Key);

// Detach all objects in the list
savedSubscriptions = 
     (List<TandemSubscription>) pm.detachCopyAll(savedSubscriptions);

pm.close();

// Now you can use the list and its content.

I Hope this helps a bit.

Upvotes: 0

bakkal
bakkal

Reputation: 55458

Try detaching the object from the graph with detachable="true":

@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Note {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long key;
...
}

Note: I totally understand the need for this, sometimes you need to retrieve the objects and lists in a controller, close the PM in the controller, then pass the models to the views. Until better solutions are known to me, this is what I am doing this on JDO/GAE with no problems so far.

List:

It seems to me that you will have to detach all the items in the list if you want to be able to use them after the PM is closed. I'd use this to get specific lists of items. A full getAll() can be very big in size.

public List<Note> getList(){
    List<Note> detachedList=null, list=null;
    try {
        String query = "select from " + Note.class.getName();
        pm = PMF.get().getPersistenceManager();
        list = (List<Note>)pm.newQuery(query).execute();            
        detachedList = new ArrayList<Note>();
        for(Note obj : list){
            detachedList.add(pm.detachCopy(obj));
        }

    } finally {
        pm.close();
    }
    return detachedList;

}

By Key:

public Note findByKey(Long key) {
    Note detachedCopy=null, object=null;
    try{
        pm= PMF.get().getPersistenceManager();
        object = pm.getObjectById(Note.class,key);
        detachedCopy = pm.detachCopy(object);
    }catch (JDOObjectNotFoundException e) {
        return null; // or whatever
    } 
    finally {
        pm.close(); // close here
    }
    return detachedCopy;

}

Afer the close, you have a detached copy, with which you can work.

Reference: http://www.datanucleus.org/products/accessplatform_1_1/jdo/attach_detach.html

Upvotes: 9

Eugene Ryzhikov
Eugene Ryzhikov

Reputation: 17369

When result is returned in the list - objects are retrieved lazily (only when you ask for them). Since your persistence manager is closed you get an exception. By "detaching" the objects your are effectively telling the persistence manager to retrieve them eagerly.

Upvotes: 1

Related Questions