使用Hibernate的@ManyToOne与@OneToMany注解时触发StackOverflowError异常
使用Hibernate的@ManyToOne与@OneToMany注解时触发StackOverflowError异常
兄弟,看你的异常栈就能一眼定位问题——这是实体类的toString方法触发了无限循环调用!
你仔细看异常日志,反复出现Ticket.toString()和Material.toString()互相调用的栈帧:Ticket的toString会遍历materials列表,调用每个Material的toString;而Material的toString又会引用ticket对象,再次触发Ticket的toString。这样无限循环下去,直接把调用栈撑爆,就抛出StackOverflowError了。
解决方法很简单,修改实体类的toString方法即可:
核心思路是避免在toString中直接引用双向关联的完整对象,改用ID或者简单属性代替,打断循环链:
- 修改
Ticket类的toString:不要直接打印materials列表,改成打印材料数量或者ID列表
@Override public String toString() { return "Ticket{" + "id=" + getId() + ", name='" + getName() + '\'' + // 只打印材料数量,避免调用Material的toString ", materialsCount=" + (materials != null ? materials.size() : 0) + '}'; }
- 修改
Material类的toString:不要直接打印ticket对象,改成打印关联Ticket的ID
@Override public String toString() { return "Material{" + "id=" + getId() + ", name='" + getName() + '\'' + // 只打印关联Ticket的ID,避免调用Ticket的toString ", ticketId=" + (ticket != null ? ticket.getId() : null) + '}'; }
额外说明:
你的查询写法(@EntityGraph或者JOIN FETCH)本身是没问题的,StackOverflow不是查询加载数据导致的,是加载后触发toString循环调用才出的问题。如果是IDE自动生成的toString(比如IDEA默认生成),记得手动去掉双向关联的字段,别图省事全选所有字段。
备注:内容来源于stack exchange,提问作者VadiMayer
相关产品推荐
相关产品推荐

