【问题标题】:Using Android & Google App Engine on Android Studio在 Android Studio 上使用 Android 和 Google App Engine
【发布时间】:2015-11-13 20:20:57
【问题描述】:

我正在开发一个带有后端的应用程序,我决定尝试将 Google App Engine 用于我的后端。由于我是 Google App Engine 的新手,所以我对逻辑有点困惑。

基本上,我有几个模型类来表示我的对象类型。假设其中一个是用户,另一个是项目。用户拥有物品,并且一件物品可以属于多个用户。所以用户 X 可以有 25 个项目,包括项目 A,用户 Y 可以有完全不同的 20 个项目,还有项目 A。

现在我的 User 类看起来像这样:

@Entity
public class User {

    @Id private Long id;
    private String name;
    private String emailAddress;
    private String photoURL;

    //All getters and setters...
}

我的 Item 类大致相同。我的一个问题是,我应该在哪里添加某种列表,例如将项目列表添加到用户中。我应该使用哪个注释?该注释将为我提供什么结果(引用、ID 或完整对象)?

与此相关的另一个问题是,在我的端点类中,如何获取特定用户拥有的项目列表(或拥有特定项目的用户列表)?

最后一个完全不相关的问题,我应该做些什么来使 id 自动递增,或者如果我在插入项目时不提供任何 id 会自动递增吗?

【问题讨论】:

  • 这完全取决于您的用例以及您想要的方式。您可以嵌入对象或对其他对象进行引用:github.com/objectify/objectify/wiki/Entities#embedded-classes 并且关于 id 高几段:“@Id 字段的类型可以是 LonglongString。如果您使用Long 并使用null id 保存一个实体,将使用该类型的标准GAE 分配器为您生成一个数值。如果您使用String 或原始long 类型,则永远不会自动生成值." Ids 可能不是增量的,我猜是随机分布的。
  • 谢谢@zapl,我得到了关于@Id 的答案。关于嵌入式类,我认为这不是我的解决方案。我希望能够独立地从两个类中获取项目。我看到了像 Ref<User> 这样的结构或像 @Load@Parent 这样的注释,但我不确定这些是否是我正在寻找的。​​span>
  • 是的,these 您正在寻找的机器人。建立关系的键或参考,自动@Loaded,以防您无论如何都要加载它们,所以对象化可以batch请求。父母可能不是,它的用途是有限的。 PS:建议阅读该文档一两次,它有点杂乱无章,但在您意想不到的地方充满了有用的信息:)
  • 我快速查看了整篇文章(会仔细阅读)。因此,在这种情况下,我可以将 List<Key<Item>> items = new ArrayList<Key<Item>>(); 行添加到我的 User 类中。但是我将如何搜索拥有相同项目的用户?你能写一个答案吗?

标签: java android google-app-engine objectify


【解决方案1】:

您可以在数据存储中搜索两件事:键和索引属性。

class Thing {
   @Id Long id;
   @Index String property;
}

有时你会保存一些实体

Thing thing1 = new Thing();
thing1.property = "yes";
Thing thing2 = new Thing();
thing2.property = "no";
ofy().save().entities(thing1, thing2).now();

现在您可以根据索引属性搜索所有实体。例如。对于property == "yes" 的所有内容。

List<Thing> things = ofy().load().type(Thing.class).filter("property", "yes").list();

将准确返回 thing1

这同样适用于属性列表。它适用于其他属性的引用/键列表。

class User {
    @Id Long id;
    @Index List<Key<Item>> items;
}

class Item {
    @Id
    Long id;
}

List<User> searchUsersWithItem(long itemId) {
    Key<Item> itemKey = Key.create(Item.class, itemId);
    return ofy().load().type(User.class).filter("items", itemKey).list();
}
List<User> searchUsersWithItem(Item item) {
    return ofy().load().type(User.class).filter("items", item).list();
}
// just loads all the referenced items in the owner
List<Item> searchItemsWithOwner(User owner) {
    return new ArrayList<Item>(ofy().load().<Item>values(owner.items).values());
}

filter 可用于引用、键和实体实例。

要找到的东西必须索引https://cloud.google.com/datastore/docs/concepts/indexes/https://github.com/objectify/objectify/wiki/Queries

你要决定的是如何为你的关系建模。有多种方法。一个用户拥有一组可以被一组用户拥有的项目实际上是一个多对多的关系。你可以像这样表示它

class User { List<Key<Item>> items; }
class Item { }

class User { }
class Item { List<Key<User>> owners; }

class User { List<Key<Item>> items; }
class Item { List<Key<User>> owners; }

甚至

class User { }
class Item { }
class Ownership { Key<Item> item; Key<User> user; }

每种方法在数据一致性和可搜索性/性能方面都有其起伏。在最初的示例中,搜索用户的所有项目是微不足道的,因为您所要做的就是加载该用户并且您拥有项目列表。另一个方向需要查询方式。

因此,就搜索性能而言,您可以从项目中的所有者列表以及用户中的项目列表中受益,因为这样您根本不需要查询。最大的缺点是数据一致性。如果您未能同时更新用户和项目,则您可能拥有认为由用户拥有的项目,而用户认为不同。

最后一种方法,使用显式的“所有权”实体本质上是传统的枢轴/连接表https://en.wikipedia.org/wiki/Many-to-many_%28data_model%29,这是将多对多关系转换为 2 个一对多关系的结果。使用它会导致容易的一致性,但查询性能最差。

父关系有时很有用,但前提是父关系需要存在实际的一对多关系。

还请注意,键与传统 SQL 数据库中的外键不同,因为它们可以在没有实体的情况下存在。因此,无论您做什么,都必须注意一致性。

【讨论】:

  • 非常感谢您的精彩回答!我对仍然有问题感到难过。当我尝试返回 List 时,出现这样的错误:Parameterized type com.googlecode.objectify.Ref&lt;&gt; not supported. 我可以通过在方法中添加 @ApiResourceProperty(ignored = AnnotationBoolean.TRUE) 注释来避免此错误,但在这种情况下,我无法在 Android 代码中使用 getter 方法。
猜你喜欢
  • 1970-01-01
  • 2014-06-14
  • 1970-01-01
  • 2012-02-11
  • 1970-01-01
  • 2015-08-31
  • 1970-01-01
  • 2015-02-15
  • 1970-01-01
相关资源
最近更新 更多