在hibernate框架下,我们经常会遇到使用多对多映射,比如学生和选修课、项目和成员等等。在这时候想把一个放着学生的List集合转换成JSON对象时,容易遇到StackOverFlowError。
Exception in thread "main" java.lang.StackOverflowError at sun.util.locale.provider.LocaleProviderAdapter.getAdapter(LocaleProviderAdapter.java:243) at java.text.DateFormatSymbols.getProviderInstance(DateFormatSymbols.java:357) at java.text.DateFormatSymbols.getInstance(DateFormatSymbols.java:335) at java.util.Calendar.getDisplayName(Calendar.java:2110) at java.text.SimpleDateFormat.subFormat(SimpleDateFormat.java:1125)
......
这个异常是怎么产生的呢,原因是在双向多对多映射会在各自的实体类中只有对方的集合,这样在进行序列化的时候会导致互相引用,学生类要引用课程类,到课程类又要引用学生类,最后导致死循环。
想要解决这个异常很简单,互相引用只要在序列化的时候忽略一种对另一种的引用,这样就不会导致无限循环引用,这时候就需要使用transient这个关键字了,在对象进行序列化的时候忽略被transient标识的成员变量,所以只要在任意一方的引用上加上transient关键字,就可以避免发生这个错误了。或者可以搜索Gson如何忽略某个属性也可以解决这个问题。下面附上代码。
课程实体类:
@Entity @Table(name = "course") public class Course implements Serializable{ private int id; //主键id private Integer cid; //课程号 private String cname; //课程名 private Double credit; //学分 private Double period; //课时 private transient Teacher teachers; //与老师类是一对多映射 private transient Set students; //与学生是多对多映射 此处省略了setter和getter方法 } 学生实体类: @Entity @Table(name = "course") public class Course implements Serializable{ private int id; //主键id private Integer cid; //课程号 private String cname; //课程名 private Double credit; //学分 private Double period; //课时 private transient Teacher teachers; //与老师类是一对多映射 private transient Set students; //与学生是多对多映射 此处省略了setter和getter方法 } 测试类: public class GsonTest { public static void main(String[] args) { StudentDAOImpl studentDAO = new StudentDAOImpl(); Gson gson = new Gson(); List studentList = new ArrayList<>(); Student student1 = studentDAO.findStudentByID(4); Student student2 = studentDAO.findStudentByID(5); studentList.add(student1); studentList.add(student2); String json = gson.toJson(studentList); System.out.println(json); } } 输出结果: [{"id":4,"sno":201419229,"sname":"曾卓","password":"123456","gender":"男","age":21,"phone":"13000000000","year":"六月 10, 1995", "courses":[{"id":1,"cid":1,"cname":"高数","credit":4.0,"period":64.0}]}, {"id":5,"sno":201419228,"sname":"小王","password":"123456","gender":"男","age":20,"phone":"13200000000","year":"一月 22, 1997","courses":[]}]