【问题标题】:Hibernate : StackOverflowException logging ManyToMany associationHibernate : StackOverflowException 记录多对多关联
【发布时间】:2014-11-14 07:24:56
【问题描述】:

org.hibernate.loader 上激活调试日志记录后,当休眠尝试记录“正在加载集合 [com.Bar#42]”之类的内容时,我遇到了 StackOverflowException

重复的堆栈是这个:

at com.Quz.toString(Quz.java:120)
at org.hibernate.type.descriptor.java.AbstractTypeDescriptor.extractLoggableRepresentation(AbstractTypeDescriptor.java:109)
at org.hibernate.type.AbstractStandardBasicType.toLoggableString(AbstractStandardBasicType.java:291)
at org.hibernate.pretty.MessageHelper.collectionInfoString(MessageHelper.java:307)
at org.hibernate.loader.Loader.loadCollection(Loader.java:2158)
at org.hibernate.loader.collection.CollectionLoader.initialize(CollectionLoader.java:62)
at org.hibernate.persister.collection.AbstractCollectionPersister.initialize(AbstractCollectionPersister.java:627)
at org.hibernate.event.def.DefaultInitializeCollectionEventListener.onInitializeCollection(DefaultInitializeCollectionEventListener.java:83)
at org.hibernate.impl.SessionImpl.initializeCollection(SessionImpl.java:1863)
at org.hibernate.collection.AbstractPersistentCollection.initialize(AbstractPersistentCollection.java:369)
at org.hibernate.collection.AbstractPersistentCollection.read(AbstractPersistentCollection.java:111)
at org.hibernate.collection.PersistentBag.toString(PersistentBag.java:506)
at java.lang.String.valueOf(String.java:2854)
at java.lang.StringBuilder.append(StringBuilder.java:128)
at com.Quz.toString(Quz.java:120)

通常,我在持有集合的对象上执行 toString,hibernate 尝试记录集合加载,在对象上调用 toString 等等。

它像这样附加在单向 @ManyToMany 上:

@Entity
@Table(uniqueConstraints = @UniqueConstraint(columnNames = { "fooId", "barId" }))
public class Quz {
    @Id
    @GeneratedValue
    protected Long id;

    protected String fooId;

    @ManyToOne
    @JoinColumn(name="barId")
    protected Bar bar;

    @ManyToMany
    @JoinTable(name = "quz_fum", joinColumns = {
            @JoinColumn(name = "fooId", referencedColumnName = "fooId"),
            @JoinColumn(name = "barId", referencedColumnName = "barId") },
                                 inverseJoinColumns = {
            @JoinColumn(name = "fumId", referencedColumnName = "fumId") })
    protected List<Fum>  fums;
}

当 joinColumns 由主键组成时它起作用(hibernate 只记录它的 id),所以我认为问题是由于我的 JoinTable 中有非主列(并且休眠尝试记录整个对象) )。

这样的 JoinTable 是 bug 还是被禁止?

谢谢

我使用的是休眠版本 3.6.0.Final。

编辑:

toString 方法没有错误。我很确定。 首先,我们可以在堆栈中除了休眠之外的递归调用之间没有任何中间。 toString 调用 hibernate 调用相同的 toString。 第二,当休眠日志关闭时,toString 运行良好。那是当我打开它时出现异常。 第三,我已经调试了足够长的时间来定位这个问题:hibernate 调用对象本身的 toString,而不是使用特定的 ManyToMany 设置调用它的 id。

我最初的问题是关于该设置:是否允许?

【问题讨论】:

  • 发布Quz#toSting()Fum#toString() 代码!!假设这两种方法之间存在递归循环..
  • 不,禁止有一个调用parent.toStringtoString 调用child.toString。除了无限循环之外,这永远不会导致任何结果。为parentchild 修复您的toString
  • @BoristheSpider child & parent 这里是什么意思?请简要说明。
  • 我建议您将 ManyToMany 转换为 OneToMany 和与映射中产阶级实体的 ManyToOne 关系。
  • 查看编辑。当休眠日志关闭时,代码中没有无限循环。

标签: java hibernate jpa many-to-many stack-overflow


【解决方案1】:

你似乎有类似以下的东西:

class Foo {

    Collection<Bar> bars;

    @Override
    public String toString() {
        return "Foo{" + "bars=" + bars + '}';
    }

}

class Bar {

    Collection<Foo> foos;

    @Override
    public String toString() {
        return "Bar{" + "foos=" + foos + '}';
    }

}

现在,当我调用bar.toStringfoo.toString 时,我进入了一个无限循环:

bar.toString
foos.toString
foo.toString
bars.toString
bar.toString

您根本无法使用像这样的toString 方法 - 您需要决定一方打印集合而另一方不这样做。

【讨论】:

    猜你喜欢
    • 2012-11-09
    • 1970-01-01
    • 1970-01-01
    • 2015-01-26
    • 1970-01-01
    • 1970-01-01
    • 2015-10-22
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多