2009-07-21 1 views
2

Я использую 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. 

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

ответ

7

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

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

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

+0

Спасибо, что многое объясняет , хотя это немного странно, имея реляционный фон db :) – Mythica

4

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

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

И PrimaryKey Long для CustomLabel ID:

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

Просто примечание: первичный ключ не обязательно должен иметь тип 'Long'. – naXa

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