关闭持久性管理器后,如何使查询结果可用

时间:2010-07-13 23:01:35

标签: java google-app-engine jdo

我正在学习GAE并且有点卡住了。如果我使用以下内容,最后确保持久性管理器已关闭,那么在尝试实际读取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)

3 个答案:

答案 0 :(得分:9)

尝试使用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

答案 1 :(得分:1)

在列表中返回结果时 - 懒惰地检索对象(仅当您要求它们时)。由于您的持久性管理器已关闭,因此会出现异常。通过“分离”对象,您有效地告诉持久性管理器急切地检索它们。

答案 2 :(得分:0)

除了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.

我希望这会有所帮助。