2012-05-14 74 views
2

开发中我有一个空的数据存储。 在线我有一个拥有数百万实体的数据存储。数据存储实体密钥冲突

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

或者,它会更简单通过本地创建密钥这样避免相撞:

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

感谢。

回答

3

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

而是使用自动键名称字符串或生成数字ID 的,先进的应用程序可能有时希望手动分配 自己的数字ID,以他们所创造的实体。但请注意, 但没有任何内容阻止数据存储将 其中一个手动数字标识分配给另一个实体。 避免这种冲突的唯一方法是让您的应用程序通过DatastoreService.allocateIds()或 AsyncDatastoreService.allocateIds()方法获取ID为 的块。数据存储区的自动ID 生成器将跟踪已使用这些 方法分配的ID,并将避免将它们重复用于其他实体,因此您可以安全使用这些ID而不会发生冲突。

必须要么产生所有数字键的手动(并以这样的方式,他们将永远不会发生碰撞),或者使用allocateIds()。除非您使用该功能,否则不能保证手动生成的任何内容不会与现有密钥相冲突。生成的键ID不像每次增加1的关系数据库中的自动增量字段。

+0

创建的,但我们在这里讨论的是将实体(因此创建密钥)放在本地数据存储中的开发模式,然后将它们导出到生产在线数据存储区在我看来,在这种情况下防止冲突的唯一方法是使用某种时间相关的ID /名称创建密钥。 –

+0

只有当您以这种方式生成100%的实体键时(即,确切地说0放不带ID),并且以这样的时间分辨率来创建零重复将被创建时,这将仅工作。如果您已经有一个以普通方式创建的实体,它可能会失败。 – mjibson

0

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

我会建议只创建一个与Google默认使用的略有不同的关键格式。只要KeyFactory使用时钟的完整精度(即不会在数秒内停止),上面的函数看起来应该工作。

+0

我从来没有设置任何密钥的任何ID。它们都是标准的,当我第一次放置实体时自动分配。在虚拟关系中,我使用KeyFactory.keyToString()。 –

+0

所有的实体都是使用'new Entity(kind)' –

0

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

a.key.id() == 1 
b.key.id() == '1' 
a.key.id() != b.key.id() 
0

您应该提供一些关于您的用例的更多信息,以便任何人提出适当的解决方案。你可以为实例的开发数据库这样就创建键:

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

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

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