Как сделать результаты запроса доступными после закрытия диспетчера сохраняемости? - PullRequest
5 голосов
/ 14 июля 2010

Я изучаю 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 ]

9 голосов
/ 14 июля 2010

Попробуйте отсоединить объект от графика с помощью 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 голос
/ 14 июля 2010

Когда результат возвращается в список - объекты извлекаются лениво (только когда вы их запрашиваете). Поскольку ваш менеджер персистентности закрыт, вы получаете исключение. «Отсоединяя» объекты, вы фактически приказываете диспетчеру постоянства быстро их извлекать.

0 голосов
/ 31 июля 2012

В дополнение к ответу от 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.

Надеюсь, это немного поможет.

...