无法在GAE JDO中保留对象

时间:2010-05-03 17:11:31

标签: java google-app-engine jdo

我对JDO和GAE都很新鲜,并且一直在努力让我的数据层坚持任何代码!

我面临的问题可能很简单,但无论我尝试什么解决方案,我似乎都找不到任何方法。

首先问题:(稍微简化,但仍包含所有必要的信息) 我的数据模型是这样的:

User:
    (primary key)
    String emailID
    String firstName

Car:
    (primary key)
    User user
    (primary key)
    String registration
    String model

这是最初的数据模型。我实现了一个CarPK对象来获取用户和注册的复合主键。然而,这遇到了各种各样的问题。 (我将保存另一个时间/问题)

然后我改变了设计:     用户:(不变)

Car:
(primary key)
String fauxPK (here fauxPK = user.getEmailID() + SEP + registration)
User user
String registration
String model

这适用于用户,它可以插入和检索用户对象。但是当我尝试插入Car Object时,我收到以下错误:

"Cannot have a java.lang.String primary key and be a child object"

Found the following helpful link about it:
http://stackoverflow.com/questions/2063467/persist-list-of-objects

去了那里建议的链接,它解释了如何创建密钥,但是他们一直在讨论“实体组”和“实体组父母”。但我似乎无法找到任何解释什么是“实体集团”或“实体集团父母”的文章或网站

我可以尝试摆弄更多的东西来弄清楚我是否可以以某种方式存储一个物体,但我正在耐心地运行,并且宁愿理解和实施,反之亦然。

所以我会感谢任何涵盖所有这些要点的文档(即使它很大),并且最好还有一些超出基本数据建模的示例。

感谢阅读这么长的帖子:)

2 个答案:

答案 0 :(得分:13)

我担心你会不喜欢这个答案。 GAE JDO必须以非常具体的方式使用,并且充满了必须遵守的限制,以便有效地使用它。向前和向后阅读文档。对于您现在看到的问题,您可能需要多次阅读本节:

http://code.google.com/appengine/docs/java/datastore/relationships.html

GAE JDO拥有拥有无主关系。有关拥有 vs 无主的示例,请参阅上面的文档。我相信您希望CarUser拥有无主关系。请注意Google App Engine文档中关于无主关系的这一启示:

http://code.google.com/appengine/docs/java/datastore/relationships.html#Unowned_Relationships

  

除了拥有的关系之外, JDO API还提供了管理无主关系的工具。 JDO的App Engine实现尚未实现此功能 ,但不要担心,您仍然可以使用Key值代替实例(或实例集合)来管理这些关系< / em>您的模型对象。

这实际上意味着,要使用GAE JDO,您不应该在Car和User类之间使用无主关系的直接引用。相反,你应该在它们之间使用间接引用,即Car应该有一个用户密钥的字段,而不是对用户本身的直接引用。您遇到的一些麻烦是因为GAE JDO无法处理您在代码中建模这种关系的方式。

Asker接着说:

  

去了那里建议的链接,它解释了如何创建密钥,但是他们一直在谈论“实体组”和“实体组父母”。但我似乎无法找到任何解释什么是“实体集团”或“实体集团父母”的文章或网站

实体组 - a graph of objects that were initially persisted together。例如,因为Car直接引用用户,当您第一次持久保存给定的Car实例时,您还将持久保存它所引用的User实例,并且此Car实例和此User实例将是同一实体的一部分组。如果此用户实例已被持久化,或者单独独立或作为另一个Car实例的一部分,则此User实例已经在另一个实体组中。 “拥有”关系应该在同一个实体组中。请注意,GAE JDO事务只能修改1个实体组 - 不再会引发异常。

实体组家长 - a top-level/root ("parent") persisted clas。在上面的示例中,当您第一次保留给定的Car实例时,您还会保留它引用的User实例。 Car实例是实体组父级。像User这样的“拥有”“子”类将其父(Car)密钥嵌入其自己的(User)密钥中。如果您要从数据库中提取Car实例然后尝试访问此车引用的用户,那么GAE JDO将使用Car的密钥来查找相应的User(因为目标用户的密钥嵌入了父Car的密钥)作为自己的关键的一部分)。

Asker收到此错误消息:

  

“不能有java.lang.String主键并且是子对象”

注意this statement in the docs

  

子类必须具有一个键字段,其类型可以包含父键信息:Key或编码为字符串的Key值。有关关键字段类型的信息,请参阅创建数据:键。

这意味着“子”类必须使用certain types of keys(即能够将其父密钥封装在子密钥内的密钥)。 LongString适用于实体组父母类,即非子类。但是,“子”类必须使用KeyKey encoded as String类型作为其键。错误消息指示Car类引用User类,就好像它是一个“拥有的”“子”类,因此User类必须使用适合于子类的键类型,但User类不使用键适合于孩子的类型(非编码字符串)。

针对眼前问题的解决方法是将Car和User建模为无主关系,方法是将Car从直接引用更改为User,而不是通过存储相关用户来进行间接引用键。整体修复可能包括仔细研究如何使您的对象模型适合GAE JDO的框架(一旦您浏览文档以尝试理解它)。这可能包括必须手动管理类之间的一些关系。

如果有任何安慰,我自己也在处理与GAE JDO相同的问题(我甚至还有一个Car类!)。

答案 1 :(得分:0)