2010-02-19 8 views
6

Dlaczego poniższy kod powoduje org.datanucleus.exceptions.NucleusUserException: Object Manager został zamknięty? Wydaje się, że wyjątek został zgłoszony w query.getResultList().Google App Engine - org.datanucleus.exceptions.NucleusUserException: Menedżer obiektów został zamknięty

public final void removeUserTokens(final String username) { 
    final Query query = entityManager.createQuery(
     "SELECT p FROM PersistentLogin p WHERE username = :username"); 
    query.setParameter("username", username); 

    for (Object token : query.getResultList()) { 
     entityManager.remove(token); 
    } 
}   

Wyjątek:

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) 
at org.datanucleus.store.appengine.query.DatastoreQuery$6.apply(DatastoreQuery.java:611) 
at org.datanucleus.store.appengine.query.DatastoreQuery$6.apply(DatastoreQuery.java:610) 
at org.datanucleus.store.appengine.query.LazyResult.resolveNext(LazyResult.java:94) 
at org.datanucleus.store.appengine.query.LazyResult$LazyAbstractListIterator.computeNext(LazyResult.java:215) 
at org.datanucleus.store.appengine.query.AbstractIterator.tryToComputeNext(AbstractIterator.java:132) 
at org.datanucleus.store.appengine.query.AbstractIterator.hasNext(AbstractIterator.java:127) 
at org.datanucleus.store.appengine.query.LazyResult$AbstractListIterator.hasNext(LazyResult.java:169) 
at com.mystuff.service.auth.PersistentTokenRepositoryImpl.removeUserTokens(PersistentTokenRepositoryImpl.java:90) 

Edit: I zwiększyło poziom dziennika datanucleus i to, co widzę.

FINE: Object Manager "[email protected]" opened for datastore "org.datanucleus.store.appen[email protected]" 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl initialiseLevel1Cache 
FINE: Level 1 Cache of type "weak" initialised 
Feb 25, 2010 7:21:38 AM org.datanucleus.JDOClassLoaderResolver classForName 
FINE: Class "java.lang.PersistentLogin" was not found in the CLASSPATH [Class resolver called from org.datanucleus.util.Imports.resolveClassDeclaration (line=177)] 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl disconnectSMCache 
FINE: Level 1 Cache cleared 
Feb 25, 2010 7:21:38 AM org.datanucleus.ObjectManagerImpl postClose 
FINE: Object Manager "[email protected]" closed 
Feb 25, 2010 7:21:38 AM com.google.apphosting.utils.jetty.JettyLogger warn 
WARNING: /j_spring_security_logout 
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) 

Odpowiedz

3

Dodanie @Transactional do metody zapobiega zamykaniu menedżera obiektów. Jednak nie jestem pewien, dlaczego zamyka się bez tego.

+1

przy założeniu, że @Transactional pochodzi z springframework –

+0

org.springframework.transaction.annotation.Transactional –

0

Nie wiem dokładnie dlaczego, ale wydaje się, że mają do czynienia z query.getResultList() lenistwo załadowane. Wygląda na to, że leniwe ładowanie zepsuło się, gdy zadzwonisz pod numer remove(token).

Jako obejście można najpierw zebrać identyfikatory/klucze dla elementów w tablicy ArrayList, a następnie w osobnej pętli usunąć je z magazynu danych?

+0

Hmmm, jest wyjątek w getResultList() tak zbierania identyfikatory/klawisze nadal wymagają getResultList () wezwanie, które, jak przypuszczam, zawiedzie. Mam wrażenie, że mam większy problem związany ze sposobem interakcji Spring i GAE. –

+0

Różnica polega na tym, że ładowanie instancji (co dzieje się podczas iteracji listy wyników w Iterator.hasNext(), a nie w metodzie getResultList()) nie będzie przeplatane wywołaniami remove(). – Thilo