首页 文章

GAE数据存储区:持久引用的对象

提问于
浏览
7

我试图将Java对象持久化到GAE数据存储区 .

我不确定如何持有具有("non-trivial")引用对象的对象 . 也就是说,假设我有以下内容 .

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)字段,我只需要添加正确的注释 . 到现在为止还挺好 . 但是,我不明白我应该如何坚持引用的自酿(儿童,父亲)类型 . 我是不是该:

  • 转换每个此类引用以保存主键(在此示例中为名称String)而不是"actual"对象,因此 Vector<Child> offsprings; 变为 Vector<String> offspringsNames;
    如果是这种情况,我如何在运行时处理对象?我是否只是从 Class.getName 查询主键,以检索refrenced对象?

  • 转换每个这样的引用以保存数据存储在正确 put() 操作时提供给我的实际密钥?也就是说, Vector<Child> offsprings; 变成 Vector<Key> offspringsHashKeys;

我已经阅读了所有官方相关的GAE文档/示例 . 在整个过程中,它们始终保持数据存储本身支持的引用(例如,在留言簿示例中,仅限字符串和长整数) .

3 回答

  • 0
    • 请参阅以下章节中的google appengine docs以获得更清晰的理解(关系,交易)

    • 还阅读了有关JDO中可分离对象的内容

    • 有关查询选择列(或字段)的信息,请阅读JDO中的fetchgroups

    对于您的问题您有几个选择:

    • 拥有一对多关系(对象将在同一实体组中)在这里,您可以在父级(父级)中拥有一个Child列表 . 这会将所有对象放在同一个实体组中 . 如果您不想在每次取神父时获取孩子,您可以从"default fetch group"删除孩子

    ``
    `@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;
    }`
    ``

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

    国际海事组织,如果我在建模一个现实世界(父亲 - 孩子)的场景,我会选择“拥有关系”的路线,因为,真的,一个人可以拥有多少个孩子;) . 当然还有一个问题,即你一次要更新多少父亲?

    希望这会有所帮助,欢呼!

  • 0

    我在jappstart项目中使用GAE / JPA创建父/子关系的示例 . 看看认证相关实体如何相互关联here .

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

    // parent
    @OneToOne(cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    private PersistentUser persistentUser;
    
    // child
    @OneToOne(mappedBy = "persistentUser", fetch = FetchType.LAZY)
    private UserAccount userAccount;
    

    一对多(参见PersistentUser.java):

    @OneToMany(mappedBy = "persistentUser", cascade = CascadeType.ALL)
    private Collection<PersistentLogin> persistentLogins;
    

    多对一(参见PersistentLogin.java):

    @ManyToOne(fetch = FetchType.LAZY)
    private PersistentUser persistentUser;
    

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

  • 0

    如果你在父亲的 ChildChild 中引用 Father 而不是你有可能出现不一致,假设父与子之间的关系是双向的(即每个_411774的父亲都应该在那个父亲的名单 Child ren . 只需要两个引用中的一个 .

    这两种解决方案都可行,但保留父亲的儿童名单有两个缺点:

    • 对Father对象的每次访问都会将列表键下载到子对象 . 如果有许多密钥,这可能会导致不必要的开销 .

    • 我认为GAE将列表的大小限制为5,000个项目 .

相关问题