2

在开发中,我有一个空的数据存储。在线我有一个包含数百万实体的数据存储。

在开发数据存储(本地)中,我放置了一个新实体(生成新密钥)。然后我导出实体并将其放入在线数据存储中(使用本地生成的密钥)。本地生成的密钥已经分配给在线数据存储中的实体的风险是什么?

或者通过像这样在本地创建密钥来避免冲突是否更简单:

for (int i = 0; i < data.size(); i++) {
    Key k = KeyFactory.createKey(kind, new Date() + i);
    // continue to creating and inserting entities...
}

谢谢。

4

4 回答 4

3

来自https://developers.google.com/appengine/docs/java/datastore/entities

高级应用程序有时可能希望手动将自己的数字 ID 分配给它们创建的实体,而不是使用键名字符串或自动生成数字 ID。但是请注意,没有什么可以阻止数据存储区将您的一个手动数字 ID 分配给另一个实体。避免此类冲突的唯一方法是让您的应用程序使用 DatastoreService.allocateIds() 或 AsyncDatastoreService.allocateIds() 方法获取一个 ID 块。数据存储区的自动 ID 生成器将跟踪已使用这些方法分配的 ID,并避免将它们重复用于另一个实体,因此您可以安全地使用此类 ID 而不会发生冲突。

您必须手动生成所有数字键(并且以它们永远不会发生冲突的方式)或使用allocateIds(). 除非您使用该功能,否则无法保证您手动生成的任何内容都不会与现有密钥发生冲突。生成的键 ID 不像关系数据库中的自动递增字段,每次递增一。

于 2012-05-14T16:52:43.633 回答
0

您应该提供有关您的用例的更多信息,以便任何人提出适当的解决方案。例如,您可以像这样在 dev 数据库上创建密钥:

  KeyFactory.createKey(entity, "dev_" + UUID.randomUUID())

另一种选择是创建一个小型实用程序或应用程序,从本地数据库中检索实体,然后将其发布到开发数据库。获取 POST 的在线服务器将创建一个新实体并从客户端分配除密钥之外的所有属性,从而让 GAE 自动生成一个新密钥。然后可以将新密钥发送回客户端,作为对 POST 操作的响应。

同样,我不知道您以后是否要更新本地数据库以与在线重新同步,但如果是这样,定义您自己的密钥的第一种方法将起作用,因为下一次同步将在线更新实体。

于 2012-05-15T21:16:16.607 回答
0

当数据存储生成键时,ID 是整数。如果您使用字符串作为 Id 生成键,那么它们将不会覆盖现有实体。

a.key.id() == 1
b.key.id() == '1'
a.key.id() != b.key.id()
于 2012-05-15T14:47:29.037 回答
0

这取决于您在实体上拥有的 ID 类型。如果它们是整数,它们很小,很容易发生冲突。

我建议只创建与 Google 默认使用的密钥格式略有不同的密钥格式。只要 KeyFactory 使用时钟的全部精度(即不会停在几秒钟),您上面的函数看起来就应该可以工作。

于 2012-05-14T16:38:35.223 回答