Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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)
like image 300
Jay Avatar asked Jul 13 '10 23:07

Jay


2 Answers

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

like image 198
bakkal Avatar answered Oct 31 '22 07:10

bakkal


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.

like image 21
Eugene Ryzhikov Avatar answered Oct 31 '22 08:10

Eugene Ryzhikov