关闭持久性管理器后如何使查询结果可用
Posted
技术标签:
【中文标题】关闭持久性管理器后如何使查询结果可用【英文标题】:How do you make query results available after closing the persistence manager 【发布时间】:2011-03-15 14:35:15 【问题描述】:我正在学习 GAE,但有点卡住了。如果我使用以下内容,并使用 finally 来确保关闭持久性管理器,则在尝试实际读取 Note 对象时会出现异常:
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();
我得到的例外是:
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)
【问题讨论】:
【参考方案1】:尝试使用detachable="true"
将对象从图表中分离出来:
@PersistenceCapable(identityType = IdentityType.APPLICATION, detachable="true")
public class Note
@PrimaryKey
@Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
private Long key;
...
注意:我完全理解这样做的必要性,有时您需要在控制器中检索对象和列表,关闭控制器中的 PM,然后将模型传递给视图。在我知道更好的解决方案之前,这就是我在 JDO/GAE 上所做的事情,到目前为止没有任何问题。
列表:
在我看来,如果您希望能够在 PM 关闭后使用列表中的所有项目,您将不得不分离它们。我会用它来获取特定的项目列表。一个完整的getAll()
可以很大。
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;
按键:
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;
收盘后,您有一个分离的副本,您可以使用它。
参考:http://www.datanucleus.org/products/accessplatform_1_1/jdo/attach_detach.html
【讨论】:
我了解这部分,我不明白的是它是一个列表。我应该遍历整个列表并分离每个项目吗? 是的,我就是这样做的。我无法让它分离列表,当我尝试这样做时,我得到一个org.datanucleus.jdo.exceptions.ClassNotPersistenceCapableException
:类“类“org.datanucleus.store.appengine.query.StreamingQueryResult”是不可持久的。似乎这就是什么如果您想分离各个项目并关闭 PM,则需要完成。【参考方案2】:
当结果在列表中返回时 - 对象被延迟检索(仅当您请求它们时)。由于您的持久性管理器已关闭,因此您会遇到异常。通过“分离”对象,您实际上是在告诉持久性管理器急切地检索它们。
【讨论】:
【参考方案3】:除了来自 bakkal 的回答,我想说你绝对需要 detachable="true"
注释参数,否则你永远不会让它工作。
要分离对象列表,您还可以使用pm.detachCopyAll(your_query_result_list)
,这将比您实现分离的迭代快一点,并且可以让您节省几行代码。感谢JDO! ;-) 但请注意,此方法需要对其结果进行显式转换。
这是我目前在上一个应用程序中使用的一个工作示例(查询中使用的键是编码字符串):
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.
我希望这会有所帮助。
【讨论】:
以上是关于关闭持久性管理器后如何使查询结果可用的主要内容,如果未能解决你的问题,请参考以下文章