我建立了一对多的关系。尽管当我从多个侧面通过ID查询对象时,一切似乎都很好,但joined列会引发stackoverflow异常,但我无法弄清楚它为什么会发生。大约我已经遵循this tutorial。
玩家实体
@Entity
@Data
public class Player {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "player_id", updatable = false, unique = true, nullable = false)
private Long id;
@Column(name = "name")
private String name;
@Column(name = "num")
private int num;
@Column(name = "position")
private String position;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "team_id")
private Team team;
}
团队实体
@Entity
@Data
public class Team {
@Id
@Column(name="team_id", updatable = false, unique = true)
private String id;
@Column(name = "name")
private String name;
@OneToMany(mappedBy = "team")
private List<Player> players;
}
我的玩家资料库
@Repository
public interface PlayerRepository extends CrudRepository<Player, Long> {
Optional<Player> findById(Long id);
}
import.sql中的数据库条目
insert into Team (team_id,name) values('Barcelona','Barcelona');
insert into Player (name,num,position,team_id) values('Andreas Inniesta', 8, 'Midfielder', 'Barcelona');
insert into Player (name,num,position,team_id) values('Lionel Messi', 10, 'Forward', 'Barcelona');
这是例外
java.lang.StackOverflowError: null
at java.lang.StringBuilder.append(StringBuilder.java:136) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
例外的根源
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_121]
at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_121]
at org.hibernate.proxy.pojo.javassist.JavassistLazyInitializer.invoke(JavassistLazyInitializer.java:84) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at mypackage.entity.Team_$$_jvst2b7_1.toString(Team_$$_jvst2b7_1.java) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Player.toString(Player.java:8) ~[classes!/:1.0-SNAPSHOT]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at java.util.AbstractCollection.toString(AbstractCollection.java:462) ~[na:1.8.0_121]
at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:510) ~[hibernate-core-5.2.17.Final.jar!/:5.2.17.Final]
at java.lang.String.valueOf(String.java:2994) ~[na:1.8.0_121]
at java.lang.StringBuilder.append(StringBuilder.java:131) ~[na:1.8.0_121]
at mypackage.entity.Team.toString(Team.java:9) ~[classes!/:1.0-SNAPSHOT]
at sun.reflect.GeneratedMethodAccessor43.invoke(Unknown Source) ~[na:na]
答案 0 :(得分:5)
如我所见,您正在使用Lombok
。
您认为您没有在创建toString
方法,但是Lombok
却不这么认为。 @Data
注释会导致生成toString
方法。
摘自Lombok
文档:
@Data
是一个方便的快捷方式注释,它捆绑了以下功能@ToString
,@EqualsAndHashCode
,@Getter
/@Setter
和@RequiredArgsConstructor
在一起:换句话说,@Data
生成所有 通常与简单POJO相关联的样板(普通 旧Java对象)和bean:所有字段的获取器,所有字段的获取器 非最终字段,以及适当的toString,equals和hashCode 涉及类领域的实现,以及 初始化所有final字段以及所有 没有初始值设定项的非最终字段已标记为@NonNull
,以确保该字段永远不会为空。
因此Lombok
为您创建了toString
方法,这导致了无限递归。
您可以通过以下方式修复它:
@ToString(exclude = "players")
public class Team {
// ...
}
或者:
@ToString(exclude = "players")
public class Team {
@OneToMany(mappedBy = "team")
@ToString.Exclude
private List<Player> players;
}
值得一提的是,如果您仍然需要在players
的{{1}}表示中包含Team
,请尝试反汇编toString
批注并仅添加您真正需要的部分需要。然后定义自己的@Data
方法。
答案 1 :(得分:0)
发生这种情况的原因是,当您要查询团队“ A”时,该列表还包含一个“ A”团队中的球员列表,这些球员本身就是他们所在的团队(“ A”团队) ,其中还包含玩家列表...您明白了,它在这种关系中无限循环无休止。为了避免StackOverflow错误,如果使用的是Jackson,则需要使用@JsonIgnore注释@OneToMany的一侧;如果使用的是普通的jsonb,则需要使用@JsonbTransient注释。
@OneToMany(mappedBy = "team")
@JsonIgnore
private List<Player> players;
OR
@OneToMany(mappedBy = "team")
@JsonbTransient
private List<Player> players;
这样,在查询球队时,球员名单将被忽略,您将避免出现错误。
答案 2 :(得分:0)
即使我也遇到过类似的问题。我在尝试保持一对多关系时遇到了StackoverFlow错误。 解决方法是。
@Data
@EqualsAndHashCode(exclude = "players") // players is @OneToMany
class Team {
@OneToMany(mappedBy = "team")
private List<Player> players;
}
这引起了问题,因为它曾经使用所有实体创建哈希码。这导致递归。