Open SherryLang opened 7 years ago
设置外键时非常容易出现的错误:Json序列化时的错误
报错信息:
2017-05-26 09:44:21.420 DEBUG [http-nio-8080-exec-10] o.s.w.s.m.m.annotation.ExceptionHandlerExceptionResolver.resolveException:133
-Resolving exception from handler [public org.springframework.data.domain.Page
<com.hikvision.rensu.cert.domain.TypeInspection> com.hikvision.rensu.cert.controller.InspectionController.getInspecionListByPage
(java.lang.Integer,java.lang.Integer)]:
org.springframework.http.converter.HttpMessageNotWritableException:
Could not write content: Infinite recursion (StackOverflowError)
(through reference chain: com.hikvision.rensu.cert.domain.TypeInspection["contents"]
->org.hibernate.collection.internal.PersistentBag[0]
->com.hikvision.rensu.cert.domain.InspectContent["owner"]
->com.hikvision.rensu.cert.domain.TypeInspection["contents"]
->org.hibernate.collection.internal.PersistentBag[0]
->com.hikvision.rensu.cert.domain.InspectContent["owner"]
->com.hikvision.rensu.cert.domain.TypeInspection["contents"]
……(重复NNNN次)
->org.hibernate.collection.internal.PersistentBag[0]
->com.hikvision.rensu.cert.domain.InspectContent["owner"]
->com.hikvision.rensu.cert.domain.TypeInspection["contents"]
->org.hibernate.collection.internal.PersistentBag[0]
->com.hikvision.rensu.cert.domain.InspectContent["owner"]
->com.hikvision.rensu.cert.domain.TypeInspection["contents"])
引号里的属性为设置的外键和domain类名。
Java实体里两个对象有关联关系,互相引用,比如,在一对多的关联关系里, 老师对象,引用了学生列表 学生对象,引用了所属老师 就构成了互相引用。 在spring MVC中,要使其中的一个对像响应成json会造成无限递归引用的异常:
org.codehaus.jackson.map.JsonMappingException:
Infinite recursion (StackOverflowError) (through reference chain:
com.entity.Person["organization"]->org.hibernate.collection.PersistentSet[0]
->com.entity.PersonOrganization["person"]->com.entity.Person["organization"]
->org.hibernate.collection.PersistentSet[0]...
因为要保持关联关系,不能在对象里解除掉关系解决这个异常,在对象的任一方的get方法上添加
注解@JsonIgnore
:
比如在学生实体Student上添加
@ManyToOne
@JoinColumn(name="TEACHER_ID")
@JsonIgnore
public Teacher getTeacher()
即可解决无限递归引用的问题。
参考:http://www.cnblogs.com/holbrook/archive/2012/12/30/2839842.html
5. Query Language 查询语言
JPA提供两种查询方式,一种是根据主键查询,使用EntityManager的find方法:
T find(Class entityClass, Object primaryKey)
另一种就是使用JPQL查询语言。JPQL是完全面向对象的,具备继承、多态和关联等特性,和hibernate HQL很相似。 使用EntityManager的createQuery方法:
Query createQuery(String qlString)
5.1 使用参数
可以在JPQL语句中使用参数。JPQL支持命名参数和位置参数两种参数,但是在一条JPQL语句中所有的参数只能使用同一种类型。
举例如下:
命令参数
Query query = em.createQuery("select p from Person p where p.personid=:Id"); query.setParameter("Id",new Integer(1));
位置参数
Query query = em.createQuery("select p from Person p where p.personid=?1"); query.setParameter(1,new Integer(1));
5.2 命名查询
如果某个JPQL语句需要在多个地方使用,还可以使用@NamedQuery 或者 @NamedQueries在实体对象上预定义命名查询。 在需要调用的地方只要引用该查询的名字即可。
例如:
5.3 排序
JPQL也支持排序,类似于SQL中的语法。例如:
Query query = em.createQuery("select p from Person p order by p.age, p.birthday desc");
5.4 聚合查询
JPQL支持AVG、SUM、COUNT、MAX、MIN五个聚合函数。例如:
Query query = em.createQuery("select max(p.age) from Person p"); Object result = query.getSingleResult(); String maxAge = result.toString();
5.5 更新和删除
JPQL不仅用于查询,还可以用于批量更新和删除。如:
5.6 更多
与SQL类似,JPQL还涉及到更多的语法,可以参考:10.2. JPQL Language Reference
注解参考:Hibernate注解使用以及Spring整合