0

У меня возникла проблема с извлечением объектов из Google Cloud Datastore с помощью JDO. Это невероятно сложно, потому что 99,5% времени мой код работает отлично, но в 0,5% случаев некоторые из данных отсутствуют, и я не могу найти последовательные шаги для репликации ошибки. Я уверен, что моя проблема связана с тем, как я настроил свою модель или как я запрашиваю хранилище данных (у меня есть подозрение, что это может быть связано с ленивой загрузкой или группой выборки по умолчанию, м не уверен).Строки, которые иногда не извлекаются с помощью запроса облачного хранилища данных (GAE, JDO, Endpoints, Java)

Прежде чем я объясню, что происходит, это поможет понять модель.

Вот упрощенная версия моей модели:

@PersistenceCapable 
@Inheritance(customStrategy = "complete-table") 
public class DataObject { 

    @PrimaryKey 
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY, defaultFetchGroup="true") 
    protected Key theKey; 

    @Persistent() 
    protected String name; 
    //... 
} 

@PersistenceCapable 
public class Class1 extends DataObject{ 

    @Persistent() 
    @Element(dependent="true") 
    private List<Class2> listOfClass2 = new ArrayList<Class2>(); 
    //... 
} 

@PersistenceCapable 
public class Class2 extends DataObject{ 

    @Persistent() 
    @Element(dependent="true") 
    private List<Class3> listOfClass2 = new ArrayList<Class3>(); 
    //... 
} 

@PersistenceCapable 
public class Class3 extends DataObject{ 

    @Persistent() 
    private String value; 
    //... 
} 

А вот код, который используется для запроса хранилища данных:

public class DataManager { 
    public DataObject get(
     User user, 
     Class type, 
     Long id) throws OAuthRequestException 
    { 
     PersistenceManager mgr = getPersistenceManager(); 
     DataObject obj = null; 

     try 
     { 
      obj = mgr.getObjectById(type, id); 
      getAllChildren(obj); 
     } 
     finally 
     { 
      mgr.close(); 
     } 

     if(obj != null) 
     { 
      return obj; 
     } 
     else 
     { 
      throw new EntityNotFoundException("Entity not found"); 
     }   
    } 

    /** 
    * Returns all of the children of the given object 
    * and their children etc. It is intended to 'touch' every object 
    * in the tree to accommodate for lazy loading. 
    */ 
    private List<StoredDataObject> getAllChildren(DataObject obj) 
    { 
     //... 
    } 
} 

Проблема заключается в том, что очень редко, то запрос будет возвращается со всеми полями «имя» на заданном уровне пустым. Например, если я получаю объект класса 1, все дочерние объекты класса 2 будут иметь атрибут «name», равный «». Данные, безусловно, находятся в хранилище данных, потому что, если я снова запустим запрос, они будут заполнены правильно. Я никогда не видел никаких других атрибутов пустым, только поле имени. Иногда это происходит на уровне Class2, иногда Class3, но никогда Class1 (насколько я видел).

Насколько я понимаю, любые атрибуты String должны автоматически включаться в группу выборки по умолчанию, но мне, возможно, не хватает аннотации, которая заставляет атрибут «name» извлекаться каждый раз?

Новое наблюдение. Когда это произойдет, оно будет происходить последовательно в течение примерно 15 минут, пока я запускаю тот же запрос с одинаковыми учетными данными пользователя. Может ли это быть чем-то связанным с кешированием?

+0

Почему это должно быть из-за ленивой загрузки или dfg? Строковое поле находится в DFG. Скорее всего, из-за «странностей» используемого вами хранилища данных. Возможно, посмотрите на журнал –

+0

Я не уверен, возможно, я ошибаюсь, глядя на них. В журналах ничего нет, что говорит о проблеме, насколько я могу видеть – Tom

+0

Я не знаю Java, но вы принимаете во внимание последовательность? –

ответ

-2

У меня очень похожая проблема. Если бы это был ответ, потому что я точно знал, что скажу, «просто допросите свои значения до регистратора до того, как вернете свой объект».

У меня есть приложение Swift iOS, подключающееся к моему Java-сервлету, работающему в GAE с сохранением JDO, в хранилище данных (встроенное и развернутое в Eclipse Kepler с плагином GAE).

Я отменил последний плагин Eclipse GAE в соответствии с некоторыми сообщениями на этом сайте из-за получения ошибок при генерации файлов rpc конечной точки, но в остальном все довольно по умолчанию.

Проблема у меня есть где у меня есть поле, представляющее внешний ключ (location.playerId ... хотя ограничений нет, и это не должно вызывать проблем в любом случае). У меня есть выход журнала в приложении Swift, который предоставляет следующее (ПРИМЕЧАНИЕ: вывод выполняется непосредственно перед вызовом конечной точки для методов INSERT и UPDATE, где строка PROXIMAL проверяет значения свойств объекта ответа при возврате. Возвращаемое местоположение POJO обрабатывается для обоих случаев в ответе.):

$$$$$$$$ ВСТАВИТЬ МЕСТО playerId: 6657911736500224

$$$$$$$$ проксимальных playerId: ноль

$$$$$$ $$ ОБНОВЛЕНИЕ МЕСТО playerId: 6657911736500224

$$$$$$$$ проксимальных playerId: ноль

Обратите внимание на значение playerId, которое было передано в качестве нулей в ответе! Методы INSERT и UPDATE являются кодом по умолчанию, созданным Eclipse (см. Список обновлений PlayerEndpoint ниже). Если я добавлю регистратор в сервлет java и выведю значение метода location.getPlayerId(), то я получаю вывод в приложении Swift следующим образом:

$$$$$$$$ INSERT LOCATION playerId: 6657911736500224

$$$$$$$$ проксимальных playerId: 6657911736500224

$$$$$$$$ UPDATE РАСПОЛОЖЕНИЕ playerId: 6657911736500224

$$$ $$$$$ PROXIMAL playerId: 6657911736500224

Как это ?! Просто опросив методы дескриптора внутри метода сервлета (и никаких изменений в том, что делает код конечной точки), и значения заполняются и возвращаются через вызов конечной точки. Похоже, что это поведение соответствует тому, что может быть истолковано как «ленивая загрузка», которая не срабатывает до явного взаимодействия.

Приведенные выше примеры встречаются с полем/методом playerId в местоположении POJO. Однако у меня такое же поведение на игровом POJO, но с методом player.getDeviceToken(). Ниже приведен код по умолчанию, сгенерированный в Eclipse в качестве конечной точки для игрока POJO, с включенными выходами регистратора.

`  
public Player updatePlayer(Player player) { 
    PersistenceManager mgr = getPersistenceManager(); 
    try { 
    if (!containsPlayer(player)) { 
     throw new EntityNotFoundException("Object does not exist"); 
    } 
    player.setUpdated(new Date()); 
    log.info("(updatePlayer) " + player.getDeviceToken()); 

    mgr.makePersistent(player); 
    log.info("(updatePlayer post persist) " + player.getDeviceToken()); 
    } finally { 
    mgr.close(); 
    } 
    log.info("(updatePlayer prereturn) " + player.getDeviceToken()); 
    return player; 
} 

`

(* Если это поможет сделать проблему Тома повторяемые и по той же причине): Есть гении, которые пришли через это и решить, что, кроме как написать некоторые значения к регистратору? !

+0

Если у вас есть вопрос, отправьте сообщение ... [вопрос] (http://stackoverflow.com/questions/ask) :-) – kleopatra

+0

Я думаю, что мой вопрос такой же, как у оригинального автора, хотя я надеюсь что мое наблюдение на допросе может дать некоторое представление о том, чтобы проблема была предсказуемо воспроизводимой. Но на самом деле мой вопрос заключается в том, разрешил ли кто-либо эту аномалию без повторного запроса или дублирования того же вопроса, который был опубликован здесь. :) –

+0

Итак, с некоторыми дополнительными испытаниями, есть один «log.info», выше которого «исправляется» проблема.Пока линия регистрации непосредственно ПОСЛЕ «mgr.makePersistent (player)»; находится в сервлете, я возвращаю свое значение обратно в приложение Swift через конечную точку. Я могу прокомментировать обе другие строки протоколирования, и я получаю значение. Странно, что строка ведения журнала непосредственно перед возвратом объекта не дает такого же решения (предположительно, потому что соединение PersistentManager закрыто). Надеюсь, это поможет людям отслеживать проблемы в своем сервлете GAE Java. :) –

 Смежные вопросы

  • Нет связанных вопросов^_^