一对多的孩子已经坚持没有父母

时间:2009-07-21 12:34:34

标签: java google-app-engine persistence

我正在将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)。除此之外,这会破坏参照完整性,这是不可取的。

2 个答案:

答案 0 :(得分:7)

您不能将现有的CustomLabel作为子元素分配给新问题。由于datanucleus处理关系的方式,每个CustomLabel实体只能属于一个Issue对象。它将父对象和子对象放在同一个实体组中。实体只能属于一个实体组。因此,假设您创建了一个名为“nastybug”的自定义标签并坚持下去。它现在属于某个实体组X.当您创建一个新问题,并继续保留它时,它将属于某个实体组Y.Datanucleus(和实际的Google数据存储区)将不允许您尝试存储组中的实体X进入Y组。

如果您希望在问题之间共享标签,则需要使用无主关系。你是不对的,你不能通过GWT的RPC机制传递密钥,所以你可能需要在发送之前将你的JDO对象翻译成其他形式。

您可以阅读有关实体组here

的信息

答案 1 :(得分:4)

将@Unowned用于您的列表:

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

您的CustomLabel ID的PrimaryKey Long:

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