【问题标题】:Unable to persist objects in GAE JDO无法在 GAE JDO 中持久化对象
【发布时间】:2011-02-15 03:10:13
【问题描述】:

我对 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

这对用户来说很好,它可以插入和检索用户对象。但是,当我尝试插入汽车对象时,出现以下错误:

"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

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

我可以尝试更多地摆弄以弄清楚我是否可以以某种方式存储一个对象,但我正在耐心地进行排序,并且也宁愿理解和实施而不是反之亦然。

因此,我将不胜感激任何涵盖所有这些要点的文档(即使它很大),并且最好有一些超出非常基本的数据建模的示例。

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

【问题讨论】:

    标签: java google-app-engine jdo


    【解决方案1】:

    恐怕你不会喜欢这个答案。 GAE JDO 必须以一种非常具体的方式使用,并且充满了限制,您必须遵守这些限制才能有效地使用它。向前和向后阅读文档。对于您现在看到的问题,您可能需要阅读此部分几次:

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

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

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

    除了拥有关系之外,JDO API 还提供了一种管理非拥有关系的工具。 JDO 的 App Engine 实现尚未实现此功能,但请放心,您仍然可以使用键值代替实例(或实例集合)来管理这些关系 的模型对象。

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

    提问者接着说:

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

    实体组 - a graph of objects that were initially persisted together。例如,因为 Car 直接引用 User,所以当您第一次持久化给定 Car 实例时,您还将持久化它所引用的 User 实例,并且此 Car 实例和此 User 实例将是同一实体的一部分团体。如果此 User 实例已经被持久化,无论是独立地还是作为另一个 Car 实例的一部分,那么这个 User 实例已经在另一个实体组中。 “拥有”关系应该在同一个实体组中。请注意,GAE JDO 事务只能修改 1 个实体组 - 任何更多都会引发异常。

    实体组父级 - a top-level/root ("parent") persisted class。在上面的例子中,当你第一次持久化一个给定的 Car 实例时,你也会持久化它引用的 User 实例。 Car 实例是实体组父级。像 User 这样的“拥有”“子”类将其父级(汽车)的密钥嵌入到自己的(用户)密钥中。如果您要从数据库中提取 Car 实例,然后尝试访问该 Car 引用的 User,则 GAE JDO 将使用 Car 的密钥来查找相应的 User(因为目标 User 的密钥嵌入了父 Car 的密钥作为自己密钥的一部分)。

    提问者收到此错误消息:

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

    注意this statement in the docs

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

    这意味着“子”类必须使用certain types of keys(即能够将其父密钥封装在子密钥中的密钥)。 LongString 适用于entity group parents类,即非子类。但是,“子”类的键必须使用 KeyKey encoded as String 类型。错误消息表明 Car 类引用 User 类,就好像它是“拥有的”“子”类一样,因此 User 类必须使用适合子类的键类型,但 User 类没有使用键适合孩子的类型(非编码字符串)。

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

    如果有什么安慰的话,我自己也在处理与 GAE JDO 相同的问题(我什至还有 Car 课程!)。

    【讨论】:

    • 首先感谢您花时间提供如此详细的答案!!!非常感谢......我最初试图模拟拥有的关系,但由于密钥的各种问题,这没有奏效。由于我的时间不多了,而且这个项目不会过多地关注 DB 模型,所以我决定使用间接引用。将回到我的下一个项目的实验中。
    • @Basil - 我认为您想要一个“无主”关系,但您编写了一个“拥有”关系(通过使用直接引用)。如this answer所示,使用间接引用是有效的解决方法 - 无需进一步“实验”。
    • 实际上从一开始我就想要一个拥有的关系。我什至制作了 PK 对象以将用户和汽车注册表示为密钥。然而这并没有奏效,还有更令人困惑的问题。目前修复是可以接受的,但我仍然有兴趣学习正确的方法。因为当前的修复将 Big Table 视为 RDBMS。
    • @Basil - 我明白了。我在想用户和汽车可以相互独立存在,因此它们之间存在“无主”关系。但是,如果您的应用程序/域中没有另一个而没有另一个,那么我明白了。太糟糕了,如何在 GAE JDO 中建模关系有很多限制 - 它无法轻松直观地表达它们。我相信当你习惯它会变得更容易。
    【解决方案2】:
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-05-12
    相关资源
    最近更新 更多