Reputation: 217
i am try to create a one to many bidirectional mapping using spring boot and spring data jpa please look the below entity
Employer Entity
@Entity
public class Employer
{
private Long id;
private String employerName;
private List<Employee> employees;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getEmployerName()
{
return employerName;
}
public void setEmployerName(String employerName)
{
this.employerName = employerName;
}
@OneToMany(cascade=CascadeType.ALL, mappedBy="employer")
public List<Employee> getEmployees()
{
return employees;
}
public void setEmployees(List<Employee> employees)
{
this.employees = employees;
}
}
Employee Entity
@Entity
public class Employee
{
private Long id;
private String employeeName;
private Employer employer;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId()
{
return id;
}
public void setId(Long id)
{
this.id = id;
}
public String getEmployeeName()
{
return employeeName;
}
public void setEmployeeName(String employeeName)
{
this.employeeName = employeeName;
}
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
public Employer getEmployer()
{
return employer;
}
public void setEmployer(Employer employer)
{
this.employer = employer;
}
}
Employer Repo
public interface EmployerServices extends JpaRepository<Employer, Long> {
}
Employee Repo
public interface EmployeeServices extends JpaRepository<Employee, Long> {
}
REST Controller is
@RestController
public class Controller {
@Autowired EmployeeServices employeeServices;
@Autowired EmployerServices employerServices;
@GetMapping("/getempr")
public Object getempr(){
return employerServices.findOne(1L);
}
}
now the problem begin start see my out put
its look like a infighting loop and my server throwing error getOutputStream() has already been called for this response.
I used @JsonBackReference & @JsonManagedReference
annotation but the problem is its working like one to many
{
"id":1,
"employerName":"employer",
"employees":[
{"id":1,"employeeName":"emp1"},
{"id":2,"employeeName":"emp2"}
]
}
if I am trying to get in the concern of many to one like all employee with employer. the output is
[
{
"id":1,
"employeeName":"emp1"
},
{
"id":2,
"employeeName":"emp2"}
]
its not showing me the employer details.
please suggets me guys what i am doing wrong. thanks in advance!!
Upvotes: 6
Views: 11811
Reputation: 148
I solved the issue by using @JsonManagedReference and @JsonBackReference json properties. So please change your code like as follows:
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JsonManagedReference
public Employer getEmployer()
@OneToMany(cascade=CascadeType.ALL, mappedBy="employer")
@JsonBackReference
public List<Employee> getEmployees()
{
Upvotes: 0
Reputation: 77
use
@JsonProperty(access = Access.WRITE_ONLY)
private List<Employee> employees;
So that it will ignore employees while printing to JSON in the response (and thus prevents the looping), but will still consider the JSON data (employee list) you pass in the request body so that it is available for persistence.
Upvotes: 0
Reputation: 173
Change your getEmployer Method like this:
@ManyToOne(cascade=CascadeType.ALL, fetch = FetchType.LAZY)
@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)
public Employer getEmployer()
{
return employer;
}
Upvotes: 0
Reputation: 634
with the JSON its a problem with bi-directional mapping. Use the below properties.
@JsonIgnoreProperties("employer")
@JsonIgnoreProperties("employees")
please keep fetching type as eager.
hope this will work.
Upvotes: 6
Reputation: 2068
You can solve your issue with two modification with annotations.
Employer.class
@Entity
public class Employer {
private Long id;
private String employerName;
@OneToMany(cascade = CascadeType.ALL,
mappedBy = "employer",
orphanRemoval = true)
private List<Employee> employees;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmployerName() {
return employerName;
}
public void setEmployerName(String employerName) {
this.employerName = employerName;
}
public List<Employee> getEmployees() {
return employees;
}
public void setEmployees(List<Employee> employees) {
this.employees = employees;
}
}
Employee.class
@Entity
public class Employee {
private Long id;
private String employeeName;
@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "employer_id")
private Employer employer;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getEmployeeName() {
return employeeName;
}
public void setEmployeeName(String employeeName) {
this.employeeName = employeeName;
}
public Employer getEmployer() {
return employer;
}
public void setEmployer(Employer employer) {
this.employer = employer;
}
}
For more information please visit this link.
Upvotes: 0
Reputation: 30474
Instead of using @JsonBackReference
and @JsonManagedReference
try to use annotation @JsonIgnoreProperties
:
@JsonIgnoreProperties("employer")
private List<Employee> employees;
@JsonIgnoreProperties("employees")
private Employer employer;
It prevents Jackson from rendering a specified properties of associated objects.
Upvotes: 10