I have created a one to many relationship. Although everything seems fine when I query the objects by id from the many to one side, the joined column throws a stackoverflow exception, that I cannot figure out why it happens. Roughly I have followed this tutorial.
Player Entity
@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;
}
Team Entity
@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;
}
My player repository
@Repository
public interface PlayerRepository extends CrudRepository<Player, Long> {
Optional<Player> findById(Long id);
}
Database entries in 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');
The player table at h2-console
This is the exception
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]
Root of the exception
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]
Furthermore debugging the error shows that some kind of internal conversion to string fails on the joined column.
As I can see you're using Lombok
.
You think that you're not creating toString
method, but Lombok
doesn't think so. The @Data
annotation causes generation of toString
method.
From Lombok
documentation:
@Data
is a convenient shortcut annotation that bundles the features of@ToString
,@EqualsAndHashCode
,@Getter
/@Setter
and@RequiredArgsConstructor
together: In other words,@Data
generates all the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate toString, equals and hashCode implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with@NonNull
, in order to ensure the field is never null.
So Lombok
created toString
method for you which leads to infinite recursion.
You can fix it by:
@Data
@ToString(exclude = "players")
public class Team {
// ...
}
Or:
@Data
public class Team {
@OneToMany(mappedBy = "team")
@ToString.Exclude
private List<Player> players;
}
Worth to mention, if you still need include players
in the Team
's toString
representation, try to disassemble the @Data
annotation and add only the parts you really need. Then define your own toString
method.
Even i faced similar problem. I got StackoverFlow Error while trying to persist one to many relationship. The solution was.
@Data
@EqualsAndHashCode(exclude = "players") // players is @OneToMany
class Team {
@OneToMany(mappedBy = "team")
private List<Player> players;
}
This was causing issue because it used to create hashcode using all the entities. This lead to recursion.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With