Добавить новый атрибут к объекту в хранилище данных?

У меня есть объект в моем хранилище данных движка приложения. На самом деле существует только один экземпляр этой сущности. Я вижу это в своей консоли администратора. Можно ли добавить новый атрибут к объекту через консоль администратора (возможно, с помощью gql)?

Прямо сейчас это выглядит примерно так:

Entity: Foo
Attributes:  mName,  mAge,  mScore

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

В худшем случае я могу написать какой-нибудь код, чтобы удалить объект, а затем сохранить новый, но да, мне просто интересно.

Спасибо

-------- Обновлять ---------

Попытался добавить новый атрибут в мой класс (используя java), и при загрузке из хранилища данных я получаю следующее:

java.lang.NullPointerException: 
  Datastore entity with kind Foo and key Foo(\"Foo\") has a null property named mGraduated.  
  This property is mapped to com.me.types.Foo.mGraduated, which cannot accept null values.

Вот как выглядит мой класс сущностей, я просто добавил новый атрибут (mGraduated), затем развернул его, а затем попытался загрузить один объект из хранилища данных (что привело к приведенному выше исключению):

@PersistenceCapable
public class Foo
{   
  @PrimaryKey
  private String k;

  /** Some old attributes, look like the following. */
  @Persistent
  @Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
  private String mName;

  ... 

  /** Tried adding the new one. */
  @Persistent
  @Extension(vendorName = "datanucleus", key = "gae.unindexed", value="true")
  private boolean mGraduated;

person user291701    schedule 19.01.2012    source источник


Ответы (3)


Вы не можете сделать это через консоль администратора, но вам не нужно удалять сущность. Вместо этого просто обновите его — хранилище данных не применяет схемы для видов. Например, если Foo является подклассом db.Model (Python), измените подкласс модели, включив в него новое свойство; получить экземпляр модели (например, по его ключу), обновить экземпляр, в том числе установить значение нового поля; и сохраните измененный экземпляр. Поскольку у вас есть только один экземпляр, это легко. Со многими такими экземплярами для обновления вы, вероятно, захотите сделать это с помощью задач очереди задач или с помощью задания mapreduce.

person Amy U.    schedule 19.01.2012
comment
Привет, да, кажется, я помню, как делал это однажды в прошлом, но теперь, когда я загружаю его с новым определением, для меня возникает исключение. Обновлен вопрос выше с более подробной информацией, это выглядит нормально? Спасибо - person user291701; 19.01.2012

Единственный способ реализовать это — использовать Boolean в качестве типа для нового свойства.

Чем в методе set вы можете принять логическое значение, это не проблема.

Если вы хотите, чтобы метод get также возвращал логическое значение.. вы также можете, но обязательно проверьте, является ли значение нулевым, и если да.. верните значение по умолчанию (например, true)

so

private Boolean newProp = null; // can also assing default value .. e.g. true;

public void setNewProp(boolean val)
{
    this.newProp = val;
}

public boolean getNewProp()
{
    if(this.newProp == null)
        return true; // Default value if not set

    return this.newProp.booleanValue();

}

Я рекомендую вам не переносить ваши данные в этом случае - это может быть очень дорого и может легко истощить вашу квоту (прочитать старые данные, создать новые, удалить старые = 3 операции для каждой записи в вашем хранилище данных)

person Marek Halmo    schedule 21.06.2012

Вы объявили новое поле mGraduated, используя логический тип примитива, который не может быть нулевым. Существующий объект не может быть загружен в класс модели, так как у него нет этого свойства. Один из вариантов — объявить это свойство с помощью логического класса, который может принимать нулевое значение.

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

person Dan Sanderson    schedule 19.01.2012
comment
Дэн, это вполне логично, но тогда каков процесс, если я действительно хочу добавить примитивный логический тип? Разве это просто невозможно, вместо этого мы должны использовать коробочный логический тип? Спасибо - person user291701; 19.01.2012
comment
Вы должны использовать тип в штучной упаковке, если может существовать объект без набора свойств. JDO/JPA не имеет способа представить unset, поэтому он заполняет значение как null, которое не может быть присвоено примитивному типу. - person Dan Sanderson; 29.01.2012