Home > Net >  Json Result has duplicates in ManyToMany with a New Entity in Spring Boot
Json Result has duplicates in ManyToMany with a New Entity in Spring Boot

Time:09-28

I'm trying to fetch all Employees with a relational table EmployeeCourse and to see how many Courses the employee has. When I use employeeRepo.findAll() method inside my Controller I got JSON result like this:

[{"firstName":"Pera","lastName":"Peric","employeeCourses":[],"employeeId":1},{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":{"firstName":"Marko","lastName":"Markovic","employeeCourses":[{"id":1,"employee":

A lot of rows were removed for brevity and other entities employees were not loaded.

my Entities look like this:

@Entity
public class Employee{

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "employee_id")
    private Integer id;
    private String firstName;
    private String lastName;
    @OneToMany(mappedBy = "employee", cascade = CascadeType.ALL)
    Set<EmployeeCourse> employeeCourses;
// getters and setters implemented
// dont have hashCode() and equals overridden
}
@Entity
public class EmployeeCourse {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;

    @ManyToOne
    @JoinColumn(name = "employee_id")
    Employee employee;
    @ManyToOne
    @JoinColumn(name = "course_id")
    Course course;
    private Date startDate;
    private Date endDate;
//have getter and setters and overridden hashCode() and equals
}
public class Course {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "course_id")
    private Integer id;
    private String name;
    private String description;

    @OneToMany(mappedBy = "course")
    Set<EmployeeCourse> employeeCourses;

}

Why do I have this double results, and how to fetch them?

CodePudding user response:

It is pretty hard to read your JSON data, but I guess that with double results I assume you are talking about the huge amount of Employee data in your JSON response. This is due to the bi-directional relationships:

  • Employee <--> EmployeeCourse: Employee has a reference to Set<EmployeeCourse> and EmployeeCourse has a reference to Employee.
  • EmployeeCourse <--> Course: EmployeeCourse has a reference to Course and Course has a reference to Set<EmployeeCourse>.

This means that when Jackson serializes your Employees it will serialize all this duplicated information.

Having said that you have now three options:

  1. You turn the bi-directional relationship into a uni-directional one, by, for example, removing the employee attribute in EmployeeCourse.
  2. If for whatever reason 1. is not possible, then you might use @JsonIgnore so that Jackson does not serialize them.
  3. If 2. is also not possible you may consider using DTOs. Using DTOs instead of plain Entities is usually advisable when returning data via a Controller. With DTOs, you clearly define whatever you want to include in the response to the caller. You can even reorganize your model so that it fits better the needs of the clients. You decouple your inner model and the model your API consumers know, making it possible to rework your inner model and still keep the same public model.

CodePudding user response:

Just put @JsonIgnor on top of the object which you don't want to expand. Ex. in course if you don't want to expand the result of employeeCourses then just do something like this

@OneToMany(mappedBy = "course")
@JsonIgnore
    Set<EmployeeCourse> employeeCourses;
  • Related