GAE Datastore: сохраняемые объекты - PullRequest
7 голосов
/ 04 июня 2010

Я пытаюсь сохранить объекты Java в хранилище данных GAE.

Я не уверен, как сохранить объект, имеющий ("нетривиальный") объект, на который есть ссылка. То есть предположим, что у меня есть следующее.

public class Father {
    String name;
    int age;
    Vector<Child> offsprings; //this is what I call "non-trivial" reference 
    //ctor, getters, setters...
}

public class Child {
    String name;
    int age;
    Father father; //this is what I call "non-trivial" reference 
    //ctor, getters, setters...
}

Поле имени уникально в каждом домене типа и считается первичным ключом.

Чтобы сохранить «тривиальные» (String, int) поля, все, что мне нужно, это добавить правильную аннотацию. Все идет нормально. Тем не менее, я не понимаю, как я должен настаивать на домашнем пиве (ребенок, отец), на которые ссылаются. Должен ли я:

  1. Преобразование каждой такой ссылки для хранения первичного ключа (в данном примере имя String) вместо «фактического» объекта, поэтому Vector<Child> offsprings; становится Vector<String> offspringsNames;?

    Если это так, то как Я обращаюсь с объектом во время выполнения? Должен ли я просто запросить первичный ключ из Class.getName, чтобы получить объекты, на которые есть ссылки?

  2. Преобразовать каждую такую ​​ссылку для хранения фактического ключа, предоставленного мне хранилищем данных при правильной операции put()? То есть Vector<Child> offsprings; становится Vector<Key> offspringsHashKeys;?

Я прочитал все официальный документ / пример GAE. Повсюду они всегда сохраняют «тривиальные» ссылки, изначально поддерживаемые хранилищем данных (например, в примере Гостевой книги, только Strings и Longs).

Ответы [ 3 ]

0 голосов
/ 04 июня 2010

Если у вас есть ссылка на Father в Child и Child рене в Отце, у вас есть вероятность несогласованности, если предположить, что отношения между Отцом и Ребенком двусторонние (т.е. каждый Child отец должен быть в списке Child ren для этого Отца). Необходима только одна из двух ссылок.

Оба решения будут работать, но ведение списка детей у отца имеет два недостатка:

  1. Каждый доступ к объекту «Отец» загружает список ключей для дочернего объекта. Если ключей много, это может привести к ненужным накладным расходам.
  2. Я считаю, что GAE ограничивает размер списка до 5000 элементов.
0 голосов
/ 06 июня 2010
  • Пожалуйста, обратитесь к документам Google Appengine в следующих разделах для более ясного понимания (Отношения, Транзакции)

  • Также читайте о съемных объектах в JDO

  • Для запросов к выборочным столбцам (или полям) читайте о группах выборок в JDO

. Для вашего вопроса у вас есть несколько вариантов:

  • Владение Отношение один ко многим (объекты будут в одной группе сущностей) Здесь вы можете иметь список Child в вашем родителе (класс Father).Это поместит все объекты в одну группу объектов.Если вы не хотите получать детей каждый раз, когда выбираете «Отца», вы можете удалить детей из «группы извлечения по умолчанию»

</p> <pre> @PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") public class Father { @PrimaryKey @Persistent private String name; @Persistent private int age; @Persistent(mappedBy = "father", defaultFetchGroup = "false") private List childern; } @PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") public class Child { @Persistent @PrimaryKey private String name; @Persistent private Father dad; } </pre> <p>

  • Неизвестные отношениягде вы храните ключи вместо ссылок:

</p> <pre> @PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") public class Father { @PrimaryKey @Persistent private String name; @Persistent private int age; @Persistent private List childern; } @PersistenceCapable(identityType = IdentityType.APPLICATION, detachable = "true") public class Child { @Persistent @PrimaryKey private String name; @Persistent private Key dad; } </pre> <p>

В этом случае вам придется управлять ссылочной целостностью, а также убедиться, что они находятся в одной группе объектов, еслиВы должны обновить / добавить их в одной транзакции

IMO, если бы я моделировал сценарий реального мира (Отцов-детей), я бы пошел по маршруту "Владение связью", поскольку, действительно, какмного детей может иметь парень;).Конечно, есть дополнительный вопрос о том, сколько отцов вы собираетесь обновлять одновременно?

Надеюсь, это поможет, ура!

0 голосов
/ 04 июня 2010

У меня есть примеры создания отношений родитель / потомок с использованием GAE / JPA в моем проекте jappstart . Посмотрите, как сущности, связанные с аутентификацией, связаны друг с другом здесь .

Один-на-один (см. UserAccount.java и PersistentUser.java):

// parent
@OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private PersistentUser persistentUser;

// child
@OneToOne(mappedBy = "persistentUser", fetch = FetchType.LAZY)
private UserAccount userAccount;

Один-ко-многим (см. PersistentUser.java):

@OneToMany(mappedBy = "persistentUser", cascade = CascadeType.ALL)
private Collection<PersistentLogin> persistentLogins;

Много-к-одному (см. PersistentLogin.java):

@ManyToOne(fetch = FetchType.LAZY)
private PersistentUser persistentUser;

Кроме того, обратите внимание в конструкторах, как KeyFactory используется для сущностей с родительским элементом и без родительского элемента.

@Id
private Key key;

// this entity has a parent
public PersistentUser(final Key key, final String username) {
    this.key = KeyFactory.createKey(key, getClass().getSimpleName(), username);
    ...
}

// this entity does not have a parent
public UserAccount(final String username) {
    this.key = KeyFactory.createKey(getClass().getSimpleName(), username);
    ....
}

Надеюсь, это полезно для вас. Я не могу сказать по вопросу, используете ли вы JPA или JDO.

...