【问题标题】:How do I create many-to-many relationships with Objectify on Google App Engine?如何在 Google App Engine 上使用 Objectify 创建多对多关系?
【发布时间】:2012-02-27 09:08:58
【问题描述】:

我找不到任何有关在 Google App Engine 上使用 Objectify 在对象之间建立多对多关系的适当方式的文档。

谁能解释一下如何做到这一点?我需要为此创建一个新的“加入”类吗?效率如何?

【问题讨论】:

    标签: java google-app-engine objectify


    【解决方案1】:

    我已经在 Objectify 4.0 中使用这种方法解决了:

    @Entity
    @Index
    public class Module {
    
    @Id
    private Long id;
    private String name;
    
    @Load
    private List<Ref<Template>> templates;
    
    
    public List<Template> getTemplates() {
        List<Template> templates = new ArrayList<Template>();
    
        for (Ref<Template> temp : this.templates) {
            templates.add(temp.get());
        }
    
        return templates;
    }
    
    public void setTemplates(List<Template> templatesParm) {
        List<Ref<Template>> templates = new ArrayList<Ref<Template>>();
    
        for (Template temp : templatesParm) {
            templates.add(Ref.create(temp));
        }
    
        this.templates = templates;
    
    }
    

    【讨论】:

    • 由于objectify中没有这样的查询,我们如何获得与多个Module关联的单个模板?
    【解决方案2】:

    让我们暂时考虑一下一对多;如果你想让一个对象 A “拥有很多”对象 B-s,那么只有两种方法可以做到:

    • 关系方式:让每个 B 指向 A。当您拥有 A0 并想要所有与之相关的 B 时,只需查询指向给定 A0 的 B。

    • NoSQL / ObjectStore 方式:使 A 有一个字段,其中包含指向 B-s 的指针(键)列表。请注意,这种方式还允许 B-s 以特定顺序排列(尽管 GAE/Java 文档相反。)

    取决于哪个最好。 ObjectStore 方式受对象大小的限制。关系方式存在一个微妙的问题,除非 A 和所有 B 都在同一个实体组中,并且您在事务中执行祖先查询(或者即使它不在事务中),您都可以保证得到所有指向该 A 的 B。但是,如果 A 和 B 跨越实体组,则有可能(尽管可能不太可能)得到一个不满足查询谓词的 B,或者错过了一个 B:https://developers.google.com/appengine/articles/transaction_isolation

    在(现在标准的)High Replication Datastore 中,事务 通常在几百毫秒内完全应用 提交返回后。但是,即使不完全 应用后,后续的读取、写入和祖先查询将始终 反映提交的结果,因为这些操作适用于任何 执行前未完成的修改。但是,跨越的查询 多个实体组无法确定是否存在 执行前未完成的修改,可能返回陈旧或 部分应用的结果。

    现在对于多多:我曾经读过一个故事,描述了在太空中上厕所;有四种组合:太空船内/外和上厕所两种。对于在船外(穿着太空服)和消除固体的最后一个组合,唯一的答案是“没有优雅的方式”(也是文章的标题):http://settlement.arc.nasa.gov/CoEvolutionBook/SPACE.HTML#ThereAin't No Graceful Way ...这也是 GAE 中多对多关系的答案。您可以使用连接类构建它们,连接的每一侧都可以通过查询或键列表来实现。

    【讨论】:

      【解决方案3】:

      这不是在 Objectify 中映射多对多关系的最佳方法。最好的方法是创建一个映射关系的实体。例如,假设您有两个对象 A 和 B,并且它们以某种方式关联。他们可以创建一个类似的类:

      Class Link{
          Key<?> master;
          key<?> slave;
      
          public Link(){
      
          }
      
          public setLink(Entity master, Entity slave){
           //initialize
      
          }
      
      }
      

      然后您可以创建一个链接实体来为关系建模。这会自动映射一对一或多对多关系

      【讨论】:

        【解决方案4】:

        您需要支持哪些类型的查询?

        最简单的解决方案是:

        @Entity
        public class StoredObject {
            @Id
            private Long id;
        
            private List<Long> relatedIds;
        }
        

        然后,给定一个StoredObject,您可以调用objectify.get(StoredObject.class, storedObject.getRelatedIds()) 来获取所有相关的ID。

        为了加快我自己的应用程序中的一些查询,我确实创建了一些连接类。费用来自写入时间(您必须维护连接),但读取时间是具有连续结果的单个索引扫描!

        【讨论】:

        • 您能说明一下您是如何实现连接类的吗?如果我在relatedIds 列表中有数千个元素,我会担心效率,特别是如果我需要一次检索relatedIds 指向的所有对象(这对我来说可能很常见)
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-09-19
        • 1970-01-01
        • 2010-12-17
        • 1970-01-01
        • 1970-01-01
        • 2011-03-17
        相关资源
        最近更新 更多