2010-02-19 49 views
6

为什么下面的代码会导致org.datanucleus.exceptions.NucleusUserException:Object Manager已关闭?该异常似乎在query.getResultList()处引发。Google App Engine - org.datanucleus.exceptions.NucleusUserException:对象管理器已关闭

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

例外:

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) 

编辑:我增加了DataNucleus将日志级别,这是我所看到的。

FINE: Object Manager "[email protected]" opened for datastore "[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) 

回答

3

将该@Transactional添加到该方法可防止关闭对象管理器。但是,我不确定为什么没有这个关闭。

+1

假设@Transactional来自springframework – 2012-05-21 23:37:59

+0

org.springframework.transaction.annotation.Transactional – 2012-05-22 05:18:03

0

我不知道到底为什么,但它似乎有query.getResultList()懒惰加载到去做。显然,当您拨打remove(token)时,延迟加载会失效。

作为解决方法,您可以首先收集ArrayList中元素的ID /键,然后在单独的循环中将它们从数据存储中删除?

+0

嗯,除了在getResultList(),所以收集IDS抛出/键仍然需要一个getResultList( )我认为会失败的电话。我觉得我遇到了一个更大的问题,这与Spring和GAE的交互方式有关。 – 2010-02-24 16:34:59

+0

不同之处在于,加载实例(在遍历Iterator.hasNext()中的结果列表时发生,而不是在getResultList()中)将不会与remove()调用交错。 – Thilo 2010-02-25 01:53:09