This error occurs because of the way your entities are mapped. See that you have bidirectional relationships between:
House
- City
House
- Contract
User
- Contract
Because you are using in those entities Lombok's annotation @Data
this is what happens:
@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
So because you are not excluding any data from any of the sides, whenever there's a need to calculate hashCode for your entity, to for example, store it inside any collection that uses hashTables, it will fail, because it will fall into an infinite loop. Same thing happens when Jackson is trying to serialize your entities. Because you have bidirectional mappings and you are not excluding any side of it, it will try recursively until StackOverflowError is thrown.
I'd advise not to use @Data
and instead try to use annotations which you really need, like @Getter
. However what you could do, to avoid this infinite loop is to exclude one side of the relationship from the equals and hashCode methods and also from the Jackson serialization/deserialization:
Contract.java
package task.homerent.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.persistence.*;
import java.util.Date;
@Data
@Entity
@Table(name = "contract", schema = "public")
public class Contract {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
// ManyToMany к Дому
@ManyToOne
@JoinColumn(name = "id_house")
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JsonIgnore
private House house;
// ManyToMany к Пользователю
@ManyToOne
@EqualsAndHashCode.Exclude
@ToString.Exclude
@JsonIgnore
@JoinColumn(name = "id_tenant")
private User user;
@Column(name = "end_date", nullable = false)
private Date endDate;
@Column(name = "start_date", nullable = false)
private Date id_house;
}
User.java
package task.homerent.model;
import lombok.Data;
import javax.persistence.*;
import java.util.List;
import java.util.Set;
@Data
@Entity
@Table(name = "users", schema = "public")
public class User {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "user")
private Set<Contract> contract;
@Column(name = "email")
private String email;
@Column(name = "password")
private String password;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
@Enumerated(value = EnumType.STRING)
@Column(name = "role")
private Role role;
@Enumerated(value = EnumType.STRING)
@Column(name = "status")
private Status status;
}
City.java
package task.homerent.model;
import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import javax.persistence.*;
import java.util.Set;
@Data
@Entity
@Table(name = "city", schema = "public")
public class City {
@Id
@GeneratedValue(strategy= GenerationType.IDENTITY)
@Column(name = "id")
private Long id;
@OneToMany(cascade = {CascadeType.DETACH, CascadeType.MERGE, CascadeType.PERSIST,
CascadeType.REFRESH
}, mappedBy = "city")
@ToString.Exclude
@EqualsAndHashCode.Exclude
@JsonIgnore
private Set<House> house;
@Column(name = "id_region", nullable = false)
private Integer id_region;
@Column(name = "name", nullable = false)
private String name;
}