消除JavaSpring多对多关系中的循环JSON
我有一个Spring应用程序,它有两个实体,它们之间有多对多的关系。有学生和小组。一个学生可以是许多小组的一部分,一个小组可以有许多学生 学生模型消除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,
@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`