Home > Back-end >  Three clases where one is bidirectional with other two make circular dependency
Three clases where one is bidirectional with other two make circular dependency

Time:07-09

First I would like to explain what I am trying to achieve here. I am making an app that lets sports teams managers manager their games, practices and such. The idea is that person can play for more than one team. My code looks like this DomainUser.java holds information about a person, name, last name, email and such.

@Entity
@Table
@AllArgsConstructor
@NoArgsConstructor
@Setter
@Getter
@With
public class DomainUser {

    @Id
    @Column(columnDefinition = "VARCHAR(36)")
    @Type(type="org.hibernate.type.UUIDCharType")
    @GeneratedValue
    private UUID id;

    @Column
    private String firebaseId;

    @Column
    private String email;

    @Column
    private String phoneNumber;

    @Column
    private String name;

    @Column
    private String lastName;

    @Column
    private Date birthDay;

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
    private List<TeamMember> teamMembers;

    private Date created;

    private Date updated;

    @PrePersist
    protected void onCreate() {
        created = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updated = new Date();
    }
}

As you can see this object also holds TeamMembers which are, players, managers or just owners. TeamMember.java

@Table(name = "teamMember")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@With
public class TeamMember {

    @Id
    @Column(columnDefinition = "VARCHAR(36)")
    @Type(type="org.hibernate.type.UUIDCharType")
    @With(AccessLevel.NONE)
    @Setter(AccessLevel.NONE)
    @GeneratedValue
    private UUID id;

    @JsonBackReference
    @JsonIgnore
    @ManyToOne(cascade = CascadeType.ALL)
    private DomainUser domainUser;

    @JsonBackReference
    @JsonIgnore
    @ManyToOne(cascade = CascadeType.ALL)
    private Team team;

    @Column(columnDefinition="tinyint(1) default 0")
    private Boolean isOwner;

    @Column(columnDefinition="tinyint(1) default 0")
    private Boolean isManager;

    @Column(columnDefinition="tinyint(1) default 1")
    private Boolean isPlayer;


    private Date created;

    private Date updated;

    @PrePersist
    protected void onCreate() {
        created = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updated = new Date();
    }
}

Which holds class Team.

@Table(name = "team")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@With

public class Team {

    @Id
    @Column(columnDefinition = "VARCHAR(36)")
    @Type(type="org.hibernate.type.UUIDCharType")
    @GeneratedValue
    private UUID id;

    @Column
    private String teamName;

    @OneToMany(cascade = CascadeType.ALL)
    @JsonManagedReference
    private List<TeamMember> teamMembers;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "invitation_id", referencedColumnName = "id")
    private InvitationLink invitationLink;

    @Column
    private double payPerPractice;

    @Column
    private String season;

    @Column(columnDefinition="tinyint(1) default 1")
    private boolean activeSeason;

    @Column
    private double payPerGame;

    private Date created;

    private Date updated;

    @PrePersist
    protected void onCreate() {
        created = new Date();
    }

    @PreUpdate
    protected void onUpdate() {
        updated = new Date();
    }
}

Whenever i try to call any of these three repositories i get error that looks something like this.

java.lang.StackOverflowError: null
    at com.kunal52.springandfirebaseauth.domain.TeamMember.toString(TeamMember.java:18) ~[classes/:na]
    at java.base/java.lang.String.valueOf(String.java:3367) ~[na:na]
    at java.base/java.lang.StringBuilder.append(StringBuilder.java:167) ~[na:na]
    at java.base/java.util.AbstractCollection.toString(AbstractCollection.java:457) ~[na:na]
    at org.hibernate.collection.internal.PersistentBag.toString(PersistentBag.java:622) ~[hibernate-core-5.4.20.Final.jar:5.4.20.Final]
    at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:429) ~[na:na]
    at com.kunal52.springandfirebaseauth.domain.Team.toString(Team.java:19) ~[classes/:na]
    at java.base/java.lang.StringConcatHelper.stringOf(StringConcatHelper.java:429) ~[na:na]
    at com.kunal52.springandfirebaseauth.domain.TeamMember.toString(TeamMember.java:18) ~[classes/:na]

Im concerned that my code is wrong because i get these errors and my databse tables look like following.

enter image description here

enter image description here

Could someone give me any insights on this pleas?

CodePudding user response:

The toString method (generated by Lombok) has a circular reference and cannot

TeamMember contains an object of type Team, and this refers to TeamMember, etc...

One way would be to exclude some property from the @ToString that Lombok generates. could you use @ToString.Exclude

@Table(name = "teamMember")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@With
@ToString
public class TeamMember {

    @JsonBackReference
    @JsonIgnore
    @ToString.Exclude
    @ManyToOne(cascade = CascadeType.ALL)
    private Team team;
}

@Table(name = "team")
@Entity
@AllArgsConstructor
@NoArgsConstructor
@Data
@With
@ToString
public class Team {

    @OneToMany(cascade = CascadeType.ALL)
    @JsonManagedReference]
    @ToString.Exclude
    private List<TeamMember> teamMembers;
}
  • Related