SherryLang / javalearning

while(Java){ learn !! }
3 stars 1 forks source link

Spring Data JPA #11

Open SherryLang opened 7 years ago

SherryLang commented 7 years ago

参考: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在实体对象上预定义命名查询。 在需要调用的地方只要引用该查询的名字即可。

例如:

@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1")
@NamedQueries({ @NamedQuery(name="getPerson1", query= "FROM Person WHERE personid=?1"), @NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1") })
Query query = em.createNamedQuery("getPerson");

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不仅用于查询,还可以用于批量更新和删除。如:

Query query = em.createQuery("update Order as o set o.amount=o.amount+10"); //update 的记录数 
int result = query.executeUpdate();
Query query = em.createQuery("delete from OrderItem item where
 item.order in(from Order as o where o.amount<100)"); 
query.executeUpdate();
query = em.createQuery("delete from Order as o where o.amount<100"); 
query.executeUpdate(); //delete的记录数

5.6 更多

与SQL类似,JPQL还涉及到更多的语法,可以参考:10.2. JPQL Language Reference

注解参考:Hibernate注解使用以及Spring整合

SherryLang commented 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()

即可解决无限递归引用的问题。