代码之家  ›  专栏  ›  技术社区  ›  Mythica

一对多的子级已被持久化,没有父级

  •  2
  • Mythica  · 技术社区  · 15 年前

    我正在使用谷歌应用引擎和谷歌网络工具包来编写一个bug跟踪器(看看这些技术有什么能力)。

    以谷歌代码的问题跟踪器为模型,我决定一个问题可以有0个或更多的标签,这些标签可以预先定义(比如在设置中)。

    标签类(自定义标签):

    @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 回复  |  直到 12 年前
        1
  •  7
  •   Peter Recore    15 年前

    不能将已存在的customLabel指定为新问题的子元素。由于DataNucleus处理关系的方式,每个CustomLabel实体只能属于一个问题对象。它将父对象和子对象放在同一个实体组中。一个实体只能属于一个实体组。所以假设您创建了一个名为“nastybug”的自定义标签并将其持久化。它现在属于某个实体组X。当您创建一个新问题并坚持这一点时,它将属于某个实体组Y。DataNucleus(以及实际的Google数据存储)不会让您尝试将一个实体从组X存储到组Y中。

    如果希望标签在问题之间共享,则需要使用无主关系。正确的做法是,不能通过GWT的RPC机制传递密钥,因此在发送之前,可能需要将JDO对象转换为其他形式。

    您可以阅读有关实体组的信息 here

        2
  •  4
  •   surfealokesea    12 年前

    使用@unowned作为列表:

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

    和primarykey long用于自定义标签ID:

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