消除JavaSpring多对多关系中的循环JSON

消除JavaSpring多对多关系中的循环JSON,java,json,spring,hibernate,Java,Json,Spring,Hibernate,我有一个Spring应用程序,它有两个实体,它们之间有多对多的关系。有学生和小组。一个学生可以是许多小组的一部分,一个小组可以有许多学生 学生模型 @Entity @Table(name = "STUDENTS") @Inheritance(strategy = InheritanceType.TABLE_PER_CLASS) @JsonIdentityInfo( generator = ObjectIdGenerators.PropertyGenerator.class,

我有一个Spring应用程序,它有两个实体,它们之间有多对多的关系。有学生和小组。一个学生可以是许多小组的一部分,一个小组可以有许多学生

学生模型

@Entity
@Table(name = "STUDENTS")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")

public class Student extends AbstractUser {

    //Fields

    @ManyToMany(fetch = FetchType.LAZY, targetEntity = Group.class)
    @JoinTable(name = "GROUPS_STUDENTS",
            joinColumns = { @JoinColumn(name = "student_id") },
            inverseJoinColumns = { @JoinColumn(name = "group_id") })
    private List<Group> groups = new ArrayList<Group>();

    //Constructors

    public Student(String password, String firstName, String lastName, String email){
        super(password, firstName, lastName, email);
    }

    public Student(){
    }

    //Setters and getters

    public List<Group> getGroups() {
        return groups;
    }

    public void setGroups(List<Group> groups) {
        this.groups = groups;
    }

}
@Entity
@Table(name = "GROUPS")
@JsonIdentityInfo(
        generator = ObjectIdGenerators.PropertyGenerator.class,
        property = "id")
public class Group implements Item, Serializable {

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

    @Column(name = "name", nullable = false, unique = true)
    private String name;

    @Column(name = "year", nullable = false, length = 1)
    private int year;

    @ManyToMany(mappedBy = "groups", targetEntity = Student.class)
    private List<Student> students;

    public Group(String name, int yearOfStudy) {
        this.setName(name);
        this.setYear(yearOfStudy);
    }
...
}

要解决jackson无限递归,可以使用
@JsonManagedReference
@JsonBackReference

@JsonManagedReference是引用的前向部分,即 正常进行序列化

@JsonBackReference是 参考–序列化中将省略它

请在此处查找更多详细信息:

公共类学生扩展AbstractUser{
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Group.class)
@JoinTable(name=“GROUPS\u STUDENTS”,
joinColumns={@JoinColumn(name=“student_id”)},
inverseJoinColumns={@JoinColumn(name=“group_id”)})
@JsonManagedReference
私有列表组=新的ArrayList();
}
公共类组实现项,可序列化{
@ManyToMany(mappedBy=“groups”,targetEntity=Student.class)
@JsonBackReference
私人名单学生;
}

如果您想动态定义要序列化的内容,可以尝试我的jackson插件,该插件是我根据以下问题开发的:


这也有助于我进行反向引用。

我已经解决了这个问题。我已经做了一个自定义序列化程序。因此,在小组中,我将通过设置自定义注释@JsonSerialize(使用=CustomStudentSerializer.class)

CustomStudentSerializer

public class CustomStudentSerializer extends StdSerializer<List<Student>> {

    public CustomStudentSerializer() {
        this(null);
    }

    public CustomStudentSerializer(Class<List<Student>> t) {
        super(t);
    }

    @Override
    public void serialize(
            List<Student> students,
            JsonGenerator generator,
            SerializerProvider provider)
            throws IOException, JsonProcessingException {

        List<Student> studs = new ArrayList<>();
        for (Student s : students) {
            s.setGroups(null);
            studs.add(s);
        }
        generator.writeObject(studs);
    }
}
公共类CustomStudentSerializer扩展了StdSerializer{
公共CustomStudentSerializer(){
这个(空);
}
公共CustomStudentSerializer(t类){
超级(t);
}
@凌驾
公共无效序列化(
列出学生名单,
JSONG发电机,
序列化提供程序(提供程序)
抛出IOException、JsonProcessingException{
列表螺柱=新的ArrayList();
(学生:学生){
s、 集合组(空);
螺柱。添加(s);
}
发电机写入对象(螺柱);
}
}
对小组也做了同样的事情。当关系已经嵌套时,我刚刚删除了students/group组件。现在它工作得很好

我花了一些时间才弄明白这一点,但我在这里发布了文章,因为它可能也会帮助其他人。

或者您可以使用DTO(数据传输对象)类。这些是纯代码类,您可以在发送数据时根据需要设置这些类。例如,对于您的案例,您可以:

UserDTO.java:

import java.util.List;

public class UserDTO {

    private int id;

    private String password;

    private String firstName;

    private String lastName;

    private String email;

    private List<GroupDTO> groups;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {
        this.password = password;
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public String getEmail() {
        return email;
    }

    public void setEmail(String email) {
        this.email = email;
    }

    public List<GroupDTO> getGroups() {
        return groups;
    }

    public void setGroups(List<GroupDTO> groups) {
        this.groups = groups;
    }

}
通过这种方式,您可以自定义将在json文件中发送的信息

假设您有一个用户类,并且希望发送所有用户信息:

    List<StudentDTO> response = new ArrayList<StudentDTO>(); //List to be send

    List<Student> students = bussinessDelegate.findAllStudents(); //Or whatever you do to get all students

    for (int i = 0; i < students.size(); i++) {

        Student student = students.get(i);          

        StudentDTO studentDTO = new StudentDTO(); //Empty constructor

        studentDTO.setEmail(student.getEmail());
        studentDTO.setFirstName(student.getFirstName());
        studentDTO.setLastName(student.getLastName());
        studentDTO.setId(student.getId());
        studentDTO.setPassword(student.getPassword());

        List<Group> studentGroups = student.getGroups();

        List<GroupDTO> studentGroupsDTO = new ArrayList<GroupDTO>();

        for (int j = 0; j < studentGroups.size(); j++) {

            Group group = studentGroups.get(j);

            GroupDTO groupDTO = new GroupDTO();

            groupDTO.setId(group.getId());
            groupDTO.setName(group.getName());
            groupDTO.setYear(group.getYear());

            studentGroupsDTO.add(groupDTO);

        }

        studentDTO.setGroups(studentGroupsDTO);
        response.add(studentDTO);
    }

    //Here you have your response list of students ready to send`
List response=new ArrayList()//要发送的列表
List students=businessdelegate.findAllStudents()//或者不管你做什么来吸引所有的学生
对于(int i=0;i
使用
@JsonIgnoreProperties
注释是另一种选择:

@实体
公共类学生扩展抽象用户{
@ManyToMany(fetch=FetchType.LAZY,targetEntity=Group.class)
@JoinTable(name=“GROUPS\u STUDENTS”,
joinColumns={@JoinColumn(name=“student_id”)},
inverseJoinColumns={@JoinColumn(name=“group_id”)})
@JsonIgnoreProperties(“学生”)
私有列表组=新的ArrayList();
}
@实体
公共类组实现项,可序列化{
@ManyToMany(mappedBy=“groups”,targetEntity=Student.class)
@JsonIgnoreProperties(“组”)
私人名单学生;
}

在这里可以找到
@JsonManagedReference
+
@JsonBackReference
@JsonIdentityInfo
@jsonignoreporties
之间的比较:

我尝试过这个方法,但这只会使它成为一个方向。我已经添加了@BackReference给学生,组字段消失了。但是,如果我切换注释,什么也不会发生。如果你不想让学生分组,你也可以使用
@JsonIgnore
注释忽略关系的一方,从而打破链条。你需要一个映射器来实现这一点,例如:**Jackson**
package temp;

public class GroupDTO {

    private int id;

    private String name;

    private int year;

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getYear() {
        return year;
    }

    public void setYear(int year) {
        this.year = year;
    }

}
    List<StudentDTO> response = new ArrayList<StudentDTO>(); //List to be send

    List<Student> students = bussinessDelegate.findAllStudents(); //Or whatever you do to get all students

    for (int i = 0; i < students.size(); i++) {

        Student student = students.get(i);          

        StudentDTO studentDTO = new StudentDTO(); //Empty constructor

        studentDTO.setEmail(student.getEmail());
        studentDTO.setFirstName(student.getFirstName());
        studentDTO.setLastName(student.getLastName());
        studentDTO.setId(student.getId());
        studentDTO.setPassword(student.getPassword());

        List<Group> studentGroups = student.getGroups();

        List<GroupDTO> studentGroupsDTO = new ArrayList<GroupDTO>();

        for (int j = 0; j < studentGroups.size(); j++) {

            Group group = studentGroups.get(j);

            GroupDTO groupDTO = new GroupDTO();

            groupDTO.setId(group.getId());
            groupDTO.setName(group.getName());
            groupDTO.setYear(group.getYear());

            studentGroupsDTO.add(groupDTO);

        }

        studentDTO.setGroups(studentGroupsDTO);
        response.add(studentDTO);
    }

    //Here you have your response list of students ready to send`