2010-07-13 2 views
5

Ich lerne GAE und bin ein bisschen fest. Wenn ich die folgende, mit einem schließlich verwenden, um sicherzustellen, dass die Persistenz-Manager geschlossen ist, erhalte ich eine Ausnahme, wenn sie versuchen, um tatsächlich die Note Objekte zu lesen:Wie machen Sie Abfrageergebnisse verfügbar nach dem Schließen der Persistenz-Manager

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(); 
    } 
    } 
} 

Die Ausnahme, die ich bekommen, ist dies:

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) 

Antwort

9

Versuchen Sie das Objekt aus dem Diagramm mit detachable="true" Abnehmen:

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

Hinweis: ich verstehe vollkommen die nee Dazu müssen Sie manchmal die Objekte und Listen in einer Steuerung abrufen, die PM im Controller schließen und dann die Modelle an die Ansichten übergeben. Bis mir bessere Lösungen bekannt sind, mache ich das bisher ohne Probleme auf JDO/GAE.

Liste:

Es scheint mir, dass Sie alle Elemente in der Liste müssen lösen, wenn Sie in der Lage sein wollen, dass sie zu verwenden, nachdem die PM geschlossen ist. Ich würde das verwenden, um bestimmte Listen von Elementen zu erhalten. Ein voller getAll() kann sehr groß sein.

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; 

} 

von 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 der Nähe, haben Sie eine freistehende Kopie, mit denen Sie arbeiten können.

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

+0

Ich verstehe diesen Teil, das Bit verstehe ich nicht, es ist eine Liste. Soll ich die ganze Liste durchgehen und jeden Gegenstand entfernen? – Jacob

+2

Ja, so habe ich das gemacht. Ich habe es nicht geschafft, eine Liste zu trennen, wenn ich das versuche, bekomme ich eine 'org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException': Die Klasse" Die Klasse "org.datanucleus.store.appengine.query.StreamingQueryResult" ist nicht beständig. Scheint, dass das getan werden muss, wenn Sie möchten, dass die einzelnen Elemente gelöst werden und schließen Sie die PM. – bakkal

+0

Ich muss kommentieren. Vielen Dank! Ich war verrückt !!! –

1

Wenn Ergebnis in der Liste zurückgegeben wird - Objekte werden lazily abgerufen (nur, wenn Sie danach fragen). Da Ihr Persistenzmanager geschlossen ist, erhalten Sie eine Ausnahme. Indem Sie die Objekte "loslösen", teilen Sie dem Persistenzmanager effektiv mit, dass er sie begierig abrufen soll.

0

Zusätzlich zu der Antwort von bakkal, würde ich sagen, dass Sie unbedingt den Annotationsparameter detachable="true" brauchen, sonst werden Sie es nie zur Arbeit bekommen. Um eine Liste von Objekten zu trennen, können Sie auch pm.detachCopyAll(your_query_result_list) verwenden, was ein wenig schneller ist als die Implementierung der Iteration, und Sie können ein paar Zeilen Code sparen. Danke JDO! ;-) Aber Vorsicht, diese Methode erfordert eine explizite Umsetzung ihrer Ergebnisse.

Hier ist ein funktionierendes Beispiel ich derzeit in meinem letzten App verwenden (der Schlüssel in der Abfrage verwendet wird, ist ein codierter 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. 

Ich hoffe, das hilft ein wenig.

Verwandte Themen