Java GAE数据存储:持久化引用对象

Java GAE数据存储:持久化引用对象,java,google-app-engine,google-cloud-datastore,Java,Google App Engine,Google Cloud Datastore,我正在尝试将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 C

我正在尝试将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)字段,我只需要添加正确的注释。到现在为止,一直都还不错。 然而,我不明白我应该如何坚持引用的家庭酿造(孩子、父亲)类型。 我应该:

  • 转换每个这样的引用以保存主键(本例中为名称字符串),而不是“实际”对象,因此
    矢量子串变成
    矢量子序列?如果是这种情况,我如何在运行时处理对象?我是否只是从
    Class.getName
    中查询主键来检索引用的对象
  • 在正确的
    put()
    操作后,转换每个这样的引用以保存数据存储提供给我的实际密钥?也就是说,
    矢量子代变为
    矢量offspringsHashKeys

  • 我已经阅读了所有与GAE相关的官方文件/示例。在整个过程中,它们始终保持数据存储本机支持的“琐碎”引用(例如,在留言簿示例中,仅字符串和长字符串)。

    我的项目中有使用GAE/JPA创建父/子关系的示例。看看与身份验证相关的实体是如何相互关联的

    一对一(请参见UserAccount.java和PersistentUser.java):

    一对多(参见PersistentUser.java):

    另外,请注意构造函数中的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。

    如果您在
    子项中引用了
    父项
    ,在父项中引用了
    子项
    人,那么假设父项和子项之间的关系是双向的,您就有可能出现不一致(即,每个
    孩子的父亲都应该在该父亲的
    孩子的
    ren列表中)。只需要两个参考中的一个

    这两种解决方案都会奏效,但将孩子名单留在父亲手中有两个缺点:

  • 对父对象的每次访问都会将列表键下载到子对象。如果有许多键,这可能会导致不必要的开销
  • 我相信GAE将列表的大小限制为5000项
    • 请参阅谷歌appengine文档以下部分,以获得更清晰的理解(关系、交易)

    • 还可以阅读JDO中的可分离对象

    • 要查询选择性列(或字段),请阅读JDO中的fetchgroups
    对于您的问题,您有几个选项:

    • 拥有一对多关系(对象将在同一实体组中)在此处,您可以在父对象(父类)中拥有子对象列表。这将把所有对象放在同一实体组中。如果您不想每次提取父对象时都提取子对象,您可以从“默认提取组”中删除子对象

    @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; } @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; } @PersistenceCapable(identityType=identityType.APPLICATION,detaccable=“true”) 公课父亲{ @主键 @持久的 私有字符串名称; @持久的 私人互联网; @持久性(mappedBy=“father”,defaultFetchGroup=“false”) 私人名单儿童; } @PersistenceCapable(identityType=identityType.APPLICATION,detaccable=“true”) 公营儿童{ @持久的 @主键 私有字符串名称; @持久的 私人爸爸; }

    • 存储键而不是引用的无主关系:

    @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; } @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; } @PersistenceCapable(identityType=identityType.APPLICATION,detaccable=“true”) 公课父亲{ @主键 @持久的 私有字符串名称; @持久的 私人互联网; @持久的 私人名单儿童; } @PersistenceCapable(identityType=identityType.APPLICATION,detaccable=“true”) 公营儿童{ @持久的 @主键 私有字符串名称; @持久的 私钥dad; }

    在这种情况下,您必须管理引用完整性,如果必须在单个事务中更新/添加它们,还必须确保它们位于同一实体组中

    在我看来,如果我要模拟一个真实世界(父亲和孩子)的场景,我会选择“拥有关系”的路线,因为,真的,一个男人可以有多少个孩子;)。当然,还有一个额外的问题,你一次要更新多少个父亲


    希望这有帮助,干杯

    你读过了吗?实际上我有点纠结于此。还不知道怎么服用。此外,我可以明确地说,孩子是父亲“拥有”的,没有父亲就没有任何意义。@Drew-应用程序引擎文档是使用JDO的一个很好的资源,但我发现编程Google app engine()对于JPA的使用是一个更好的参考。这个网站有很多很好的参考资料、示例和食谱。你有#1的来源吗?在我看来,延迟加载不应该有太多开销。此外,entities键已经包含获取其父项所需的信息,无论是否存在通过@ManyToOne等定义的实际关系。请看2009年发布的Google I/O演示文稿的第20页。。。我不知道不一致的部分。然而,在我的场景中,获取父对象通常意味着fetchi @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; }