Один-ко-многим ребенок уже сохранился без родителя - PullRequest
2 голосов
/ 21 июля 2009

Я использую Google App Engine в сочетании с Google Web Toolkit для написания трекера ошибок (чтобы увидеть, на что способны технологии).

По образцу трекера проблем Google Code я решил, что проблема может иметь 0 или более меток, которые можно определить заранее (скажем, в настройках).

Класс этикетки (CustomLabel):

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class CustomLabel implements Serializable {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    private String encodedKey;

    @Persistent
    @Extension(vendorName="datanucleus", key="gae.pk-id", value="true")
    private Long keyId;

    /**
     * label caption.
     */
    @Persistent
    private String caption;

    // Unimportant getters / setters
}

Теперь родительский класс (выпуск):

@PersistenceCapable(identityType = IdentityType.APPLICATION)
public class Issue implements Serializable {
    private static final long serialVersionUID = 1L;

    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    // Replacing the Long key by this key doesn't make a difference
    // @PrimaryKey
    // @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    // @Extension(vendorName="datanucleus", key="gae.encoded-pk", value="true")
    // private String encodedKey;

    @Persistent
    private String summary;

    @Persistent
    private String description;

    @Persistent 
    private ArrayList<CustomLabel> labels;

    // Other details
}

Когда я пытаюсь сохранить новую проблему с существующими CustomLabels, я получаю следующее исключение:

org.datanucleus.exceptions.NucleusUserException: Detected attempt to establish Issue(11) as the parent of CustomLabel(1) but the entity identified by CustomLabel(1) has already been persisted without a parent.  A parent cannot be established or changed once an object has been persisted.

Как это можно решить? Я не могу использовать ключи и создавать неизвестные отношения, так как я отправляю объекты во внешний интерфейс GWT (который компилируется в Javascript и com.google.appengine.api.datastore.Key не поддерживается). Кроме того, это нарушит ссылочную целостность, что нежелательно.

Ответы [ 2 ]

7 голосов
/ 22 июля 2009

Вы не можете назначить уже существующую CustomLabel в качестве дочернего элемента для новой проблемы. Каждая сущность CustomLabel может принадлежать только одному объекту Issue, благодаря тому, как datanucleus обрабатывает отношения. Он помещает родительский и дочерний объекты в одну группу объектов. Сущность может принадлежать только одной группе сущностей. Допустим, вы создаете пользовательскую метку под названием «nastybug» и сохраняете ее. Теперь он принадлежит какой-то группе сущностей X. Когда вы создаете новую проблему и продолжаете ее настаивать, она будет принадлежать некоторой группе сущностей Y. Datanucleus (и реальное хранилище данных Google) не позволит вам попытаться сохранить сущность из группы X в группу Y.

Если вы хотите, чтобы ярлыки распределялись между проблемами, вам нужно будет использовать неизвестные отношения. Вы правы в том, что вы не можете передать Ключ через RPC-механизм GWT, поэтому вам может потребоваться перевести ваши объекты JDO в какую-либо другую форму перед их отправкой.

Вы можете прочитать о группах сущностей здесь

4 голосов
/ 31 октября 2012

Используйте @Unowned для вашего списка:

import com.google.appengine.datanucleus.annotations.Unowned;
...
@Persistent
@Unowned
private List<Category> categories;

И PrimaryKey Long для вашего идентификатора CustomLabel:

@Persistent(valueStrategy=IdGeneratorStrategy.IDENTITY)
@PrimaryKey
private Long id;
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...