Java Persistence API 定义了一种查询语言,具有与SQL 相类似的特征,JPQL 是完全面向对象的,具备继承、多态和关联等特性。
1、命名查询
你可以在实体bean 上预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把经常使用的查询语句定义成命名查询,代码如下:
你可以在实体bean 上预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。通常把经常使用的查询语句定义成命名查询,代码如下:
@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1") @Entity @Table(name = "Person") public class Person implements Serializable{
如果你需要定义多个命名查询,应在@javax.persistence.NamedQueries 注释里定义@NamedQuery,代码如下:
@NamedQueries({ @NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1"), @NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1") }) @Entity@Table(name = "Person")public class Person implements Serializable{
当命名查询定义好了之后,我们就可以通过名称执行其查询。代码如下:
Query query = em.createNamedQuery("getPerson");query.setParameter(1, 1);
2、如果不显式注明,EJB3 QL 中默认为asc 升序。
3、查询部分属性
Query query = em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
Query query = em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
4、查询中使用构造器(Constructor)
private String QueryConstructor(){ //我们把需要的两个属性作为SimplePerson 的构造器参数,并使用new 函数。 Query query = em.createQuery("select new com.foshanshop.ejb3.bean.SimplePerson(p.name,p.sex) from Person p order by p.personid desc"); //集合中的元素是SimplePerson 对象 List result = query.getResultList(); StringBuffer out = new StringBuffer("*************** QueryConstructor 结果打印 ****************<BR>"); if (result!=null){ Iterator iterator = result.iterator(); while( iterator.hasNext() ){ SimplePerson simpleperson = (SimplePerson) iterator.next(); out.append("人员介绍:"+ simpleperson.getDescription()+ "<BR>"); } } return out.toString(); }
5、聚合函数
目前EJB3 QL 支持的聚合函数包括:
1. AVG()
2. SUM()
3. COUNT() ,返回类型为Long
4. MAX()
5. MIN()
和SQL 一样,如果聚合函数不是select...from 的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select 语句中除了聚合函数外的所有属性
Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex");如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"WHERE"语句。
//返回人数超过1 人的性别 Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex having count(*)>?1"); query.setParameter(1, new Long(1));6、关联(join)
left out join/left join 等都是允许符合条件的右边表达式中的Entiies 为空。
//获取26 岁人的订单,不管Order 中是否有OrderItem Query query = em.createQuery("select o from Order o left join o.orderItemswhere o.ower.age=26 order by o.orderid");inner join 要求右边的表达式必须返回Entities
Query query = em.createQuery("select o from Order oinner join o.orderItemswhere o.ower.age=26 order by o.orderid");fetch 提供了一种灵活的查询加载方式来提高查询的性能。在默认的查询中,Entity 中的集合属性默认不会被关联,集合属性默认是缓加载( lazy-load )。
"select o from Order o inner joino.orderItems where o.ower.age=26 order by o.orderid"
为了查询N 个Order,我们需要一条SQL 语句获得所有的Order 的原始对象属性, 但需要另外N 条语句获得每Order 的orderItems 集合属性。为了避免N+1 的性能问题,我们可以利用joinfetch 一次过用一条SQL 语句把Order 的所有信息查询出来
//获取26 岁人的订单,Order 中必须要有OrderItem Query query = em.createQuery("select o from Order o inner join fetcho.orderItems where o.ower.age=26 order by o.orderid");7、排除相同的记录DISTINCT
Query query = em.createQuery("select DISTINCT o from Order o inner join fetch o.orderItems order by o.orderid");8、在查询中使用参数查询时,参数类型可以是Entity 的实例
Query query = em.createQuery("select o from Order o where o.ower =?1 order by o.orderid"); Person person = new Person(); person.setPersonid(new Integer(1)); //设置查询中的参数 query.setParameter(1,person); List result = query.getResultList();
9、使用操作符NOT
//查询除了指定人之外的所有订单 Query query = em.createQuery("select o from Order o where not(o.ower =?1) order by o.orderid"); Person person = new Person(); person.setPersonid(new Integer(2)); //设置查询中的参数 query.setParameter(1,person);10、 使用操作符BETWEEN
Query query = em.createQuery("select o from Order as o where o.amount between 300 and 1000");
11、 使用操作符IN
Query query = em.createQuery("select p from Person as p where p.age in(26,21)");
12、 使用操作符LIKE
Query query = em.createQuery("select p from Person as p where p.name like 'li%'");
13、使用操作符IS NULL
Query query = em.createQuery("select o from Order as o where o.ower is not null order byo.orderid");
14、 使用操作符IS EMPTY
IS EMPTY 是针对集合属性(Collection)的操作符。可以和NOT 一起使用
IS EMPTY 是针对集合属性(Collection)的操作符。可以和NOT 一起使用
Query query = em.createQuery("select o from Order as o where o.orderItems is not empty order byo.orderid");
15、
使用操作符EXISTS [NOT]EXISTS 需要和子查询配合使用
//如果不存在订单号为10 的订单,就获取id 为1 的OrderItem query = em.createQuery("select oi from OrderItem as oi where oi.id=1 and not exists (select o from Order o where o.orderid=10)"); //如果存在订单号为1 的订单,就获取所有OrderItem Query query = em.createQuery("select oi from OrderItem as oi where exists (select o from Order o where o.orderid=1)");
16、字符串函数EJB3 QL 中定义的字符串函数包括:
1. CONCAT 字符串拼接
2. SUBSTRING 字符串截取
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位
Query query = em.createQuery("select p.personid, concat(p.name, '_foshan') from Person as p");
17、 计算函数
EJB3 QL 中定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
SIZE 取集合的数量
子查询可以用于WHERE 和HAVING 条件语句中
EJB3 QL 中定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
SIZE 取集合的数量
//查询所有Order 的订单号及其订单项的数量 Query query = em.createQuery("select o.orderid, size(o.orderItems) from Order as o group by o.orderid");20 子查询
子查询可以用于WHERE 和HAVING 条件语句中
21 结果集分页
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页,QueryAPI 有两个接口方法可以解决这个问题:setMaxResults( ) 和setFirstResult( )
setMaxResults 方法设置获取多少条记录,setFirstResult 方法设置从结果集中的那个索引开始获取(假如返回的记录有3 条,容器会自动为记录编上索引,索引从0 开始,依次为0,1,2)
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页,QueryAPI 有两个接口方法可以解决这个问题:setMaxResults( ) 和setFirstResult( )
setMaxResults 方法设置获取多少条记录,setFirstResult 方法设置从结果集中的那个索引开始获取(假如返回的记录有3 条,容器会自动为记录编上索引,索引从0 开始,依次为0,1,2)
public List getPersonList(int max,int whichpage) { try { int index = (whichpage-1) * max; Query query = em.createQuery("from Person p order by personid asc"); List list = query.setMaxResults(max). setFirstResult(index). getResultList(); em.clear();//分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收 return list; } catch (Exception e) { e.printStackTrace(); return null; } }