【问题标题】:How do I setup a ManyToOne relationship using JPA with AppEngine?如何使用 JPA 和 AppEngine 设置多对一关系?
【发布时间】:2013-02-22 20:32:47
【问题描述】:

我一直在尝试使用 JPA 与 AppEngine 中的 2 个实体建立关系,但目前遇到了这个错误:

java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Infinite recursion (StackOverflowError) (through reference chain

我的实体如下所示:

@Entity
public class MyUser {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "user", cascade = CascadeType.ALL)
    private List<MyMessage> messages;
}

还有这个:

@Entity
public class MyMessage {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Key key;

    @ManyToOne(optional=false)
    private MyUser user;

}

用户已经存在,这里是我插入新消息并得到递归错误的地方:

EntityManager mgr = getEntityManager();
MyUser myuser = mgr.find(MyUser.class, KeyFactory.createKey("MyUser", user.getEmail()));
mymessage.setUser(myuser);
myuser.addMessage(mymessage);
mgr.persist(myuser);
mgr.persist(mymessage);

我应该如何在 JPA 和 AppEngine 指南中设置这种关系?谢谢!

更新

我的问题是涉及杰克逊,而不是 JPA。 JPA 关系很好,但是我需要删除该关系并通过代码对其进行管理,因为它在序列化消息时导致无限递归,这些消息指的是引用消息的用户等等。我还必须确保将 MyMessage 中的用户属性注释为 @Transient 以避免持久性抱怨持久化已存在的子级拥有的父级。

【问题讨论】:

    标签: google-app-engine jpa google-cloud-endpoints


    【解决方案1】:

    我不知道端点序列化这些类的合理方式。从您当前的代码生成的 JSON 看起来类似于以下内容:

    // 1
    {
      "key": "foo",
      "messages": [
        {
          "key": "bar",
          "user": {
            // repeat 1
        },
      // and so on...
    }
    

    最好的办法是定义一个(或多个)类以通过网络发送,而不是定义 JPA 实体,后者定义 JSON 的深度无限多。

    【讨论】:

    • 我不确定我明白为什么。根据示例,我正在使用受支持的注释。为什么说不支持这些数据类?此外,我得到的错误与持久性有关,而不是与云端点有关。任何帮助表示赞赏,谢谢! github.com/branflake2267/CloudEndPoints/blob/master/…
    • 对不起,我记得看到一个包含列表或集合属性的类的示例,但我现在找不到。尽管不鼓励 AppEngine 的数据存储,但我想我必须扁平化数据 rdbms 样式。
    • 您可以返回一个列表(作为返回类型或在实体类中)。不支持的是无限地相互引用的类(这就是错误所在)。您应该定义一个不同的类,以一种不会导致此类递归的方式对您的响应进行建模,并将数据存储实体中的数据移动到这些新类中,然后再将它们返回到端点中。我会更新我的答案以反映这一点。
    • 我现在明白了,这确实有道理。谢谢!
    【解决方案2】:

    显然,您的消息与 JPA 持久性无关,而是与杰克逊有关(大概与您如何将这些对象传回有关?)。只有您知道从哪里调用它。您的帖子中并不清楚您的实际持久性操作是否成功,因为您没有生成堆栈跟踪和其余持久性代码(例如 Jackson 调用的来源)

    【讨论】:

    • 你有一个 1-N bidir 关系(对我来说似乎没问题),并保留一个用户和一条消息( pm.makePersistent(message) 是不必要的,因为它在连接后的第一次调用中保持不变给用户)。如果你真的想看看事情是否被持久化,应该在 DEBUG 级别配置“日志”。但是我希望任何库(包括杰克逊)都会抛出带有堆栈跟踪的异常,否则人们将无法看到该软件在哪里丢失了情节......可能它与 bidir 关系有一些问题,因此无限递归。
    • 我将云端点与 appengine 一起使用,杰克逊的详细信息通过该 SDK 处理。所以你是说我的注释、结构和实体管理器代码看起来都很好?不幸的是,日志中没有更多错误。
    • 感谢您提供额外的见解。我正在再次查看日志,并将尝试删除 persist(mymessage) 调用。
    • 我仍然遇到无限递归错误:java.io.IOException: com.google.appengine.repackaged.org.codehaus.jackson.map.JsonMappingException: Unable to get a resource (through reference chain: com.piusvelte.mosaic.gwt.server.MosaicUser["messages"]-&gt;java.util.ArrayList[0]- 后跟 Infinite recursion (StackOverflowError) (through reference chain: java.util.ArrayList[0]-&gt;com.piusvelte.mosaic.gwt.server.MosaicMessage["user"]-
    • 我猜这个问题的答案stackoverflow.com/questions/10191671/…
    猜你喜欢
    • 1970-01-01
    • 2017-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-03-19
    相关资源
    最近更新 更多