无法从实体输出数据



不可能将房屋实体中的公寓显示为一个完整的列表并按ID单独显示。当我转到页面时,我得到一个错误,即无限循环

'(无法写入JSON:无限递归(stackoverlowerror(;嵌套异常com.fasterxml.Jackson.databind.JsonMappingException:无限递归(StackOverflowError((通过链接链:task.home pageproject.model.home[quot;city"]->task.home page project.model.city$HibernateProxy$ikPQOTJQ[quot。

HouseRestController

@GetMapping("/{id}")
@PreAuthorize("hasAuthority('user:read')")
public House userPostInfo(@PathVariable(value = "id") Long id) {
Optional<House> house = houseRepository.findById(id);
List<House> res = new ArrayList<>();
house.ifPresent(res::add);
return res.stream().filter(houses -> houses.getId().equals(id))
.findFirst()
.orElse(null);
}

出现此错误是因为实体的映射方式。请注意,您在以下各项之间存在双向关系:

House-City

House-Contract

User-Contract

因为您在这些实体中使用Lombok的注释@Data,所以会发生以下情况:

@Data生成所有通常与简单的POJO(普通的旧Java对象(和beans:getters字段,所有非最终字段的setter,以及适当的toString,equals和hashCode实现,它们涉及类

因此,因为您没有从任何一边排除任何数据,所以每当需要为实体计算hashCode时,例如,将其存储在任何使用hashTables的集合中,它都会失败,因为它将陷入无限循环。当Jackson试图序列化您的实体时,也会发生同样的事情。因为你有双向映射,并且你没有排除它的任何一边,所以它会递归地尝试,直到StackOverflowError被抛出。

我建议不要使用@Data,而是尝试使用您真正需要的注释,如@Getter。然而,为了避免这种无限循环,您可以从equals和hashCode方法以及Jackson序列化/反序列化中排除关系的一侧:

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;
}

最新更新