'I have one stackOverflow error with relation OneToMany
I have one stackOverflowerror, between two entities, one entities is client, and other's is annonce, annonce, having one author client, with relation entities list column join... If i asking for list of client, the stack over coming with listing from annonce and relist altime in annonce with author, and that's is circulary...How to avoid that's and keep one listing form annonce by each client ?...
Client:
@Entity
@Table(name = "client")
@Getter
@Setter
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Client implements UserDetails {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(length = 16, name = "client_id", nullable = false, updatable = false)
private UUID client_id;
@Column(nullable = false)
private String username;
@Column(nullable = false)
private String firstname;
@Column(nullable = false)
private String lastname;
@Column(unique = true, nullable = false)
private String email;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String nationalite;
@Column(nullable = false)
private String rue;
@Column(nullable = false)
private String numero;
@Column(nullable = false)
private String cp;
@Column(nullable = false)
private String ville;
@Column(nullable = false)
private String pays;
@Column(nullable = true)
private String tel;
@Column(nullable = true)
private String imgType;
@Column(columnDefinition = "BLOB")
private byte[] profilePicture;
@Column(nullable = false)
private Boolean accountNonExpired;
@Column(nullable = false)
private Boolean accountNonLocked;
@Column(nullable = false)
private Boolean credentialsNonExpired;
@Column(nullable = false)
private Boolean enabled;
@ElementCollection(targetClass = Role.class, fetch = FetchType.EAGER)
@CollectionTable(name = "roles", joinColumns = @JoinColumn(name = "client_id"))
@Enumerated(EnumType.STRING)
private List<Role> roles;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "createdAt", insertable = false, columnDefinition = "DATETIME DEFAULT NOW()")
private Date createdAt;
@Column(name = "updateAt", nullable = true, columnDefinition = "DATETIME")
private Date updateAt;
@OneToMany(mappedBy = "cartFrom")
private Collection<Cart> cartList = new ArrayList<>();
Here-->
@OneToMany(mappedBy = "author", targetEntity = Annonce.class, orphanRemoval = true, cascade = CascadeType.ALL)
private Collection<Annonce> annonceList = new ArrayList<>();
@OneToMany(mappedBy = "conversationOf")
private Collection<Conversation> conversationList = new ArrayList<>();
@OneToMany(mappedBy = "orderedFrom")
private Collection<Ordered> orderedList = new ArrayList<>();
@Override
public Collection<? extends GrantedAuthority> getAuthorities() {
return null;
}
@Override
public boolean isAccountNonExpired() {
return true;
}
@Override
public boolean isAccountNonLocked() {
return true;
}
@Override
public boolean isCredentialsNonExpired() {
return true;
}
@Override
public boolean isEnabled() {
return true;
}
}
Annonce :
@Entity
@Table(name = "annonce")
@Getter
@Setter
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Annonce {
@Id
@GeneratedValue(generator = "UUID")
@GenericGenerator(name = "UUID", strategy = "org.hibernate.id.UUIDGenerator")
@Column(length = 16, name = "annonce_id", nullable = false, updatable = false)
private UUID annonce_id;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private String title;
@Column(nullable = false)
private String description;
@Column(nullable = false)
private double price;
@Column(nullable = false)
private int quantity;
@Column(nullable = false)
private String salesTerms;
And here -->
@ManyToOne
@JoinColumn(name = "author_client_id")
private Client author;
@OneToOne(mappedBy = "annonce", fetch = FetchType.LAZY)
@JoinColumn(name = "annoncepicture_id", nullable = false)
private AnnoncePicture annoncepicture;
@ManyToMany
@JoinTable(name = "annonce_carts",
joinColumns = @JoinColumn(name = "annonce_id"),
inverseJoinColumns = @JoinColumn(name = "cart_id"))
private List<Cart> cartList = new ArrayList<>();
@OneToMany(mappedBy = "conversationOnAnnonce")
private Collection<Conversation> conversationList = new ArrayList<>();
@ManyToMany(mappedBy = "annonceList")
private List<Categorie> categorieList = new ArrayList<>();
@Enumerated
@ElementCollection(fetch = FetchType.LAZY)
private List<State> states;
@OneToMany(mappedBy = "noteFor")
private Collection<Note> noteList;
@Temporal(TemporalType.TIMESTAMP)
@Column(name = "createdAt", insertable = false, columnDefinition = "DATETIME DEFAULT NOW()")
private Date createdAt;
@Column(name = "updateAt", nullable = true, columnDefinition = "DATETIME")
private Date updateAt;
@Column(nullable = false)
private String categorie;
}
and than here is explain of problem...
"client_id": "58b80786-29d3-4ba9-b657-659cc32890a4",
"username": "[email protected]",
"firstname": "Christophe",
"lastname": "Cuypers",
"email": "[email protected]",
"password": "$2a$10$chNqhZ73r.kfEU/ZJ7M7XeU3Dck.q9XMRXUURc0ZnWMggJFRZat/m",
"nationalite": "Français",
"rue": "Rue de Beauraing",
"numero": "11B6",
"cp": "6920",
"ville": "Wellin",
"pays": "France",
"tel": "474/474.206",
"imgType": null,
"profilePicture": null,
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"roles": [
"ADMIN",
"CLIENT",
"BUYER",
"MODERATOR"
],
"createdAt": "2022-04-11T12:01:59.000+00:00",
"updateAt": null,
"cartList": [],
"annonceList": [
{
"annonce_id": "a41a271c-f9bb-4644-894d-fc5245c2b054",
"name": "Ordinateur",
"title": "Vielle ordinateur",
"description": "Vielle ordinateur avec écran",
"price": 250.0,
"quantity": 1,
"salesTerms": "A prendre sur place",
"author": {
"client_id": "58b80786-29d3-4ba9-b657-659cc32890a4",
"username": "[email protected]",
"firstname": "Christophe",
"lastname": "Cuypers",
"email": "[email protected]",
"password": "$2a$10$chNqhZ73r.kfEU/ZJ7M7XeU3Dck.q9XMRXUURc0ZnWMggJFRZat/m",
"nationalite": "Français",
"rue": "Rue de Beauraing",
"numero": "11B6",
"cp": "6920",
"ville": "Wellin",
"pays": "France",
"tel": "474/474.206",
"imgType": null,
"profilePicture": null,
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"roles": [
"ADMIN",
"CLIENT",
"BUYER",
"MODERATOR"
],
"createdAt": "2022-04-11T12:01:59.000+00:00",
"updateAt": null,
"cartList": [],
"annonceList": [
{
"annonce_id": "a41a271c-f9bb-4644-894d-fc5245c2b054",
"name": "Ordinateur",
"title": "Vielle ordinateur",
"description": "Vielle ordinateur avec écran",
"price": 250.0,
"quantity": 1,
"salesTerms": "A prendre sur place",
"author": {
"client_id": "58b80786-29d3-4ba9-b657-659cc32890a4",
"username": "[email protected]",
"firstname": "Christophe",
"lastname": "Cuypers",
"email": "[email protected]",
"password": "$2a$10$chNqhZ73r.kfEU/ZJ7M7XeU3Dck.q9XMRXUURc0ZnWMggJFRZat/m",
"nationalite": "Français",
"rue": "Rue de Beauraing",
"numero": "11B6",
"cp": "6920",
"ville": "Wellin",
"pays": "France",
"tel": "474/474.206",
"imgType": null,
"profilePicture": null,
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"roles": [
"ADMIN",
"CLIENT",
"BUYER",
"MODERATOR"
],
"createdAt": "2022-04-11T12:01:59.000+00:00",
"updateAt": null,
"cartList": [],
"annonceList": [
{
"annonce_id": "a41a271c-f9bb-4644-894d-fc5245c2b054",
"name": "Ordinateur",
"title": "Vielle ordinateur",
"description": "Vielle ordinateur avec écran",
"price": 250.0,
"quantity": 1,
"salesTerms": "A prendre sur place",
"author": {
"client_id": "58b80786-29d3-4ba9-b657-659cc32890a4",
"username": "[email protected]",
"firstname": "Christophe",
"lastname": "Cuypers",
"email": "[email protected]",
"password": "$2a$10$chNqhZ73r.kfEU/ZJ7M7XeU3Dck.q9XMRXUURc0ZnWMggJFRZat/m",
"nationalite": "Français",
"rue": "Rue de Beauraing",
"numero": "11B6",
"cp": "6920",
"ville": "Wellin",
"pays": "France",
"tel": "474/474.206",
"imgType": null,
"profilePicture": null,
"accountNonExpired": true,
"accountNonLocked": true,
"credentialsNonExpired": true,
"enabled": true,
"roles": [
"ADMIN",
"CLIENT",
"BUYER",
"MODERATOR"
],
Thanks for your helps...Have great day...
Solution 1:[1]
Use FetchType.LAZY on the members which cause the circularity. Also, if you log the entity at any time or have any identity checks, also use @ToString.Exclude and @EqualsAndHashCode.Exclude (or, better, annotate the classes with @EqualsAndHashCode(onlyExplicitlyIncluded = true) and the id members with @EqualsAndHashCode.Include()).
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Matei Macoveiciuc |
