为什么双向映射会产生无限循环?
why does bidirectional mapping give infinate loop?
我正在做一个项目。我想给出一对一的双向关系。我得到无限循环 json。为什么我不知道。我在互联网上推荐。我无法清楚地了解它。请给我一个解决方案。
@GetMapping(value = "/employees")
List<Employee> getEmployees() {
return this.employeeRepository.findAll();
}
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
package com.example.jpa.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="EMPLOYEES")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="EMP_ID", unique = true, nullable = false)
private Long empId;
private String name;
private String department;
private Long salary;
@Column(name="JOINED_ON")
private Date joinedOn;
@OneToOne(fetch = FetchType.EAGER, mappedBy = "employee", cascade = CascadeType.ALL)
private EmpDetails empDetails;
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public Long getSalary() {
return salary;
}
public void setSalary(Long salary) {
this.salary = salary;
}
public Date getJoinedOn() {
return joinedOn;
}
public void setJoinedOn(Date joinedOn) {
this.joinedOn = joinedOn;
}
public EmpDetails getEmpDetails() {
return empDetails;
}
public void setEmpDetails(EmpDetails empDetails) {
this.empDetails = empDetails;
}
@Override
public String toString() {
String resp = this.empId+" | "+this.name+" | "+this.department+" | "+this.salary+" | "+this.joinedOn;
if(this.empDetails != null) {
resp += "|"+this.empDetails.toString();
}
return resp;
}
}
package com.example.jpa.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="EMP_DETAILS")
public class EmpDetails {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ED_ID", unique = true, nullable = false)
private Long edId;
private String address;
private String gender;
@Column(name="YEARS_OF_SERVICE")
private Long yearsOfService;
@Column(name="BANK_ACCOUNT")
private String bankAccount;
@OneToOne
@JoinColumn(name="EMP_ID")
private Employee employee;
public Long getEdId() {
return edId;
}
public void setEdId(Long edId) {
this.edId = edId;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Long getYearsOfService() {
return yearsOfService;
}
public void setYearsOfService(Long yearsOfService) {
this.yearsOfService = yearsOfService;
}
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public String toString() {
return this.gender+" | "+this.address+" | "+this.yearsOfService+" | "+this.bankAccount;
}
}
无限JSON:
[
{
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
..............
}]
因为您的 Employee
实体有一个 EmpDetails
并且 EmpDetails
有一个 Employee
实体。在 EmpDetails
实体的员工字段上使用 @JsonIgnore
注释使其工作
@OneToOne
@JsonIgnore
@JoinColumn(name="EMP_ID")
private Employee employee;
当 Jackson 试图将您的实体序列化为 json 时。他应该序列化员工字段。为此,他将尝试序列化 empDetails 字段。因此再次尝试序列化此 empDetails 中的员工字段,这样他将处于循环无限循环中。
解决方案是防止序列化现场员工。在 class 员工中,您在员工字段中添加 @JsonIgnore。
@OneToOne
@JoinColumn(name="EMP_ID")
@JsonIgnore
private Employee employee;
我正在做一个项目。我想给出一对一的双向关系。我得到无限循环 json。为什么我不知道。我在互联网上推荐。我无法清楚地了解它。请给我一个解决方案。
@GetMapping(value = "/employees")
List<Employee> getEmployees() {
return this.employeeRepository.findAll();
}
@Repository
public interface EmployeeRepository extends JpaRepository<Employee, Long> {
}
package com.example.jpa.model;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="EMPLOYEES")
public class Employee implements Serializable {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="EMP_ID", unique = true, nullable = false)
private Long empId;
private String name;
private String department;
private Long salary;
@Column(name="JOINED_ON")
private Date joinedOn;
@OneToOne(fetch = FetchType.EAGER, mappedBy = "employee", cascade = CascadeType.ALL)
private EmpDetails empDetails;
public Long getEmpId() {
return empId;
}
public void setEmpId(Long empId) {
this.empId = empId;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public Long getSalary() {
return salary;
}
public void setSalary(Long salary) {
this.salary = salary;
}
public Date getJoinedOn() {
return joinedOn;
}
public void setJoinedOn(Date joinedOn) {
this.joinedOn = joinedOn;
}
public EmpDetails getEmpDetails() {
return empDetails;
}
public void setEmpDetails(EmpDetails empDetails) {
this.empDetails = empDetails;
}
@Override
public String toString() {
String resp = this.empId+" | "+this.name+" | "+this.department+" | "+this.salary+" | "+this.joinedOn;
if(this.empDetails != null) {
resp += "|"+this.empDetails.toString();
}
return resp;
}
}
package com.example.jpa.model;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.OneToOne;
import javax.persistence.Table;
@Entity
@Table(name="EMP_DETAILS")
public class EmpDetails {
@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Column(name="ED_ID", unique = true, nullable = false)
private Long edId;
private String address;
private String gender;
@Column(name="YEARS_OF_SERVICE")
private Long yearsOfService;
@Column(name="BANK_ACCOUNT")
private String bankAccount;
@OneToOne
@JoinColumn(name="EMP_ID")
private Employee employee;
public Long getEdId() {
return edId;
}
public void setEdId(Long edId) {
this.edId = edId;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public String getGender() {
return gender;
}
public void setGender(String gender) {
this.gender = gender;
}
public Long getYearsOfService() {
return yearsOfService;
}
public void setYearsOfService(Long yearsOfService) {
this.yearsOfService = yearsOfService;
}
public String getBankAccount() {
return bankAccount;
}
public void setBankAccount(String bankAccount) {
this.bankAccount = bankAccount;
}
public Employee getEmployee() {
return employee;
}
public void setEmployee(Employee employee) {
this.employee = employee;
}
@Override
public String toString() {
return this.gender+" | "+this.address+" | "+this.yearsOfService+" | "+this.bankAccount;
}
}
无限JSON:
[
{
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
"department": "Documentation",
"salary": 10000,
"joinedOn": "2019-09-17T08:12:24.362+0000",
"empDetails": {
"edId": 1,
"address": "Bangalore",
"gender": "Male",
"yearsOfService": 4,
"bankAccount": "00343466",
"employee": {
"empId": 1,
"name": "Nataraja G",
..............
}]
因为您的 Employee
实体有一个 EmpDetails
并且 EmpDetails
有一个 Employee
实体。在 EmpDetails
实体的员工字段上使用 @JsonIgnore
注释使其工作
@OneToOne
@JsonIgnore
@JoinColumn(name="EMP_ID")
private Employee employee;
当 Jackson 试图将您的实体序列化为 json 时。他应该序列化员工字段。为此,他将尝试序列化 empDetails 字段。因此再次尝试序列化此 empDetails 中的员工字段,这样他将处于循环无限循环中。 解决方案是防止序列化现场员工。在 class 员工中,您在员工字段中添加 @JsonIgnore。
@OneToOne
@JoinColumn(name="EMP_ID")
@JsonIgnore
private Employee employee;