【问题标题】: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)

【问题讨论】:

    标签: java google-app-engine jdo


    【解决方案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.
      

      我希望这会有所帮助。

      【讨论】:

        猜你喜欢
        • 2018-07-10
        • 2011-10-25
        • 2016-08-14
        • 2011-03-23
        • 2014-12-20
        • 2011-03-16
        • 2011-05-10
        • 2015-01-13
        • 2011-07-17
        相关资源
        最近更新 更多