JPA + GSON:仅在服务器重新启动后,查询才会导致Stackoverflow

凯·朱格尔

最近,我们遇到了JPA和@ManyToOne / @OneToMany关系的查询问题,从而导致stackoverflow。但这仅在由于创建实体而重新启动应用程序服务器时发生

问题:当我正常部署部署了war文件的应用程序服务器时,无论如何我都可以在数据库中填充一些内容并对其进行查询。但是,当我在不清除数据库的情况下重新启动服务器并尝试执行相同的查询时,我会得到奇怪的行为:

我得到一个Stackoverflow异常:

java.lang.StackOverflowError

at java.lang.StringBuffer.append(StringBuffer.java:224)

at java.io.StringWriter.write(StringWriter.java:84)

at java.io.StringWriter.append(StringWriter.java:126)

at java.io.StringWriter.append(StringWriter.java:24)

at com.google.gson.stream.JsonWriter.beforeValue(JsonWriter.java:610)

at com.google.gson.stream.JsonWriter.open(JsonWriter.java:317)

at com.google.gson.stream.JsonWriter.beginObject(JsonWriter.java:300)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:190)

at com.google.gson.Gson$FutureTypeAdapter.write(Gson.java:879)

at com.google.gson.internal.bind.TypeAdapterRuntimeTypeWrapper.write(TypeAdapterRuntimeTypeWrapper.java:68)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$1.write(ReflectiveTypeAdapterFactory.java:89)

at com.google.gson.internal.bind.ReflectiveTypeAdapterFactory$Adapter.write(ReflectiveTypeAdapterFactory.java:195)

[...]

出于完整性考虑:我的实体具有以下关系:

任务实体:

@OneToMany(mappedBy = "mission", cascade=CascadeType.ALL)  
private Collection<Mission2Mission> children;

@OneToMany(mappedBy = "parent", cascade=CascadeType.ALL)
@Retention(RetentionPolicy.RUNTIME) 
@Target(ElementType.FIELD)
private Collection<Mission2Mission> parents;

Mission2Mission实体:

@ManyToOne  
@Retention(RetentionPolicy.RUNTIME)   
@Target(ElementType.FIELD)  
private Mission parent;  

@ManyToOne   
private Mission mission;

这意味着,父母知道自己的孩子,反之亦然,但是至少应该通过使用tentionPolicy避免典型的GSON Stackoverflow,因为父母被排除在外。

我不知道这整个问题是否与JPA或GSON有关,但真正令我感到奇怪的是,为什么仅在重新启动服务器后才会发生这种情况。它表示某种会话问题,我无法弄清楚,也没有找到关于此特定问题的任何其他线程或问题,所以我只在这里提问。

我知道有一些懒惰和急切的访存类型,但是使用它们并不能解释,为什么这个问题仅在服务器重启时出现。

非常感谢,凯

凯·朱格尔

好的,我终于找到了答案,找到答案很痛苦:

在任务实体中,我将孩子和父母保留在收藏中。但是,其中只有一个要由GSON序列化,这个“父母”被排除在外(@GsonExclude = @Retention(RetentionPolicy.RUNTIME)&@Target(ElementType.FIELD),我刚刚在前面做了明确提及。

下面的代码是任务实体的“错误”版本:

@OneToMany(mappedBy = "mission", fetch=FetchType.LAZY, cascade=CascadeType.ALL)@XmlTransient 
private Collection<Mission2Mission> children;

@OneToMany(mappedBy = "parent", fetch=FetchType.LAZY, cascade=CascadeType.ALL)@GsonExclude@XmlTransient
private Collection<Mission2Mission> parents;

还有其他人看到这个问题吗?“ mappedBy”映射错误的引用。当然,当尝试检索任务的子级时,我需要将其映射到“父级”字段中,以查找所有条目,其中给定任务是父级。“父母”也一样。检索所有我需要查找的父母地图Mission2Mission实体,其中“任务”(孩子)是这个。

上面的代码反之亦然,导致可能的inf循环,因为Mission2Mission实体(请参见上文)以相反的方式进行操作((实际上排除了父代而不是子代))。

交换映射字段(任务和父对象)的工作就像是一种魅力。花了足够长的时间才能弄清楚。

无论如何,感谢您的输入。此处的缓存提示大大提高了调试速度:)

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章