Java Persistence API 定义了一种查询语言,具有与SQL 相类似的特征,JPQL 是完全面向对象的,具备继承、多态和关联等特性 (可参考持久化产品使用手册,如Hibernate,Kodo,Toplink)
查询都是大小写不敏感的
1.查询
select count(p) from Person p
2.命名查询
@NamedQueries(
{
@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1"),
@NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1")
}
)
...
Query query=em.createNamedQuery("getPerson");
3.排序
排序和SQL的语法类似
select p from Person p order by p.age desc, p.birthday asc
4.查询Entity Bean 的部分属性
Query query = em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
//集合中的元素不再是Person,而是一个Object[]对象数组
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//取每一行
Object[] row = ( Object[]) iterator.next();
//数组元素的顺序和查询时的参数顺序一样
int personid = Integer.parseInt(row[0].toString());
String PersonName = row[1].toString();
}
5.查询中使用构造器
EJB3 QL 支持将查询的属性结果直接作为一个java class 的构造器参数,并产生实体作为结果返回
例
//我们把需要的两个属性作为SimplePerson 的构造器参数,并使用new 函数。
Query query = em.createQuery("select new xxx.xxx.SimplePerson(p.name,p.sex) from Person p order by p.personid desc");
//集合中的元素是SimplePerson 对象
List result = query.getResultList();
6.聚合查询
和SQL 一样,如果聚合函数不是select...from 的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select 语句中除了聚合函数外的所有属性,如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"WHERE"语句
EJB3 QL 支持的聚合函数:
1. AVG() : select avg(p.age) from Person p
2. SUM() : select sum(p.age) from Person p
3. COUNT() : select count(p) from Person p
返回类型为Long,注意count(*)语法在hibernate 中可用,但在toplink 其它产品中并不可用
4. MAX() : select max(p.age) from Person p
5. MIN() : select min(p.age) from Person p
GROUP BY的例子:
//返回男女生各自的总人数
Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex");
//集合中的元素不再是Person,而是一个Object[]对象数组
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//取每一行
Object[] row = (Object[]) iterator.next();
//数组中的第一个值是sex
boolean sex = Boolean.parseBoolean(row[0].toString());
//数组中的第二个值是聚合函数COUNT 返回值
String sextotal = row[1].toString();
}
HAVING例子
Query query = em.createQupery("select p.sex, count(p) from Person p group by p.sex having count(*)>?1");
7:关联
在EJB3 QL 中,仍然支持和SQL 中类似的关联语法:
left out join/left join
都是允许符合条件的右边表达式中的Entiies为空
//获取26 岁人的订单,不管Order 中是否有OrderItem
Query query = em.createQuery("select o from Order o left join o.orderItems where o.ower.age=26
order by o.orderid");
不加上left join也可以,需要显式使用left join/left outer join 的情况会比较少
inner join
右边的表达式必须返回Entities
//获取26 岁人的订单,Order 中必须要有OrderItem
Query query = em.createQuery("select o from Order o inner join o.orderItems where o.ower.age=26
order by o.orderid");
left join/inner join fetch
left/left out/inner join fetch 提供了一种灵活的查询加载方式来提高查询的性能。在默认的查询中,Entity 中的集合属性默认不会被关联,集合属性默认是缓加载( lazy-load ),这样的查询性能上有不足的地方。为了查询N 个Order,我们需要一条SQL 语句获得所有的Order 的原始对象属性, 但需要另外N 条语句获得每个Order 的orderItems 集合属性。为了避免N+1 的性能问题,我们可以利用join fetch 一次过用一条SQL 语句把Order 的所有信息查询出来.
//获取26 岁人的订单,Order 中必须要有OrderItem
Query query = em.createQuery("select o from Order o inner join fetch o.orderItems where
o.ower.age=26 order by o.orderid");
使用fetch,这个查询只会产生一条SQL 语句,比原来需要N+1 条SQL 语句在性能上有了极大的提升
8.排除相同的记录DISTINCT
使用关联查询,我们很经常得到重复的对象,如下面语句:
"select o from Order o inner join fetch o.orderItems order by o.orderid "
当有N 个orderItem 时就会产生N 个Order,而有些Order 对象往往是相同的
使用DISTINCT 关键字来排除掉相同的对象 :
Query query = em.createQuery("select DISTINCT o from Order o inner join fetch o.orderItems
order by o.orderid");
不同的Order对象只有一个
9.比较Entity
在查询中使用参数查询时,参数类型除了String, 原始数据类型( int, double 等)和它们的对象类型( Integer, Double等),也可以是Entity 的实例.
//查询某人的所有订单
<!-- Order的ower属性是一个Person对象 -->
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();
...
10.批量更新(Batch Update)
EJB3 QL 支持批量更新.
//把所有订单的金额加10
Query query = em.createQuery("update Order as o set o.amount=o.amount+10");
//update 的记录数
int result = query.executeUpdate();
11.批量删除(Batch Remove)
EJB3 QL 支持批量删除
//把金额小于100的订单删除,先删除订单子项,再删除订单
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");
int result = query.executeUpdate();//delete的记录数
...
12.使用操作符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);
List result = query.getResultList();
...
13.使用操作符BETWEEN
//查询金额在300 到1000 之间的订单
Query query = em.createQuery("select o from Order as o where o.amount between 300 and 1000");
List result = query.getResultList();
...
14.使用操作符IN
//查找年龄为26,21 的Person
Query query = em.createQuery("select p from Person as p where p.age in(26,21)");
List result = query.getResultList();
...
15.使用操作符LIKE
//查找以字符串"li"开头的Person
Query query = em.createQuery("select p from Person as p where p.name like 'li%'");
List result = query.getResultList();.
...
16.使用操作符IS NULL
//查询含有购买者的所有Order
Query query = em.createQuery("select o from Order as o where o.ower is not null order by
o.orderid");
List result = query.getResultList();
...
17.使用操作符IS EMPTY
IS EMPTY 是针对集合属性(Collection)的操作符.可以和NOT 一起使用
//查询含有订单项的所有Order
Query query = em.createQuery("select o from Order as o where o.orderItems is not empty order by
o.orderid");
List result = query.getResultList();
...
18.使用操作符EXISTS
[NOT]EXISTS 需要和子查询配合使用
//如果存在订单号为1 的订单,就获取所有OrderItem
Query query = em.createQuery("select oi from OrderItem as oi where exists (select o from Order o
where o.orderid=1)");
List result = query.getResultList();
...
19.字符串函数
EJB3 QL 定义了内置函数方便使用.这些函数的使用方法和SQL 中相应的函数方法类似.EJB3 QL 中定义的字符串函数包括:
1. CONCAT 字符串拼接
//查询所有人员,并在姓名后面加上字符串"_some"
Query query = em.createQuery("select p.personid, concat(p.name, '_some') from Person as p");
...
2. SUBSTRING 字符串截取
//查询所有人员,只取姓名的前三个字符
Query query = em.createQuery("select p.personid, substring(p.name,1,3) from Person as p");
...
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位
20.计算函数
EJB3 QL 中定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
//查询所有Order 的订单号及其总金额/10 的余数
Query query = em.createQuery("select o.orderid, mod(o.amount, 10) from Order as o");
...
SIZE 取集合的数量
//查询所有Order 的订单号及其订单项的数量
Query query = em.createQuery("select o.orderid, size(o.orderItems) from Order as o group by
o.orderid");
21.子查询
子查询可以用于WHERE 和HAVING 条件语句中
//查询年龄为26 岁的购买者的所有Order
Query query = em.createQuery("select o from Order as o where o.ower in(select p from Person as p
where p.age =26) order by o.orderid");
...
22.结果集分页
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页,QueryAPI 有两个接口方法可以解决这个问题:setMaxResults( ) 和setFirstResult( )
setMaxResults 方法设置获取多少条记录setFirstResult 方法设置从结果集中的那个索引开始获取(假如返回的记录有3 条,容器会自动为记录编上索引,索引从0 开始,依次为0,1,2)
例子:
Query query = em.createQuery("from Person p order by personid asc");
List list = query.setMaxResults(max).setFirstResult(index).getResultList();
em.clear();//分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收
...
如果我们需要显示大量的实体Bean,假如记录成千上万,通过简单的循环处理,我们将很快消耗完内存,为此我们需要在显示了一部分实体bean 之后调用EntityManager.clear()及时把这些实体bean 从EntityManager 分离出来,让Java VM 对他们进行垃圾回收
查询都是大小写不敏感的
1.查询
select count(p) from Person p
2.命名查询
@NamedQueries(
{
@NamedQuery(name="getPerson", query= "FROM Person WHERE personid=?1"),
@NamedQuery(name="getPersonList", query= "FROM Person WHERE age>?1")
}
)
...
Query query=em.createNamedQuery("getPerson");
3.排序
排序和SQL的语法类似
select p from Person p order by p.age desc, p.birthday asc
4.查询Entity Bean 的部分属性
Query query = em.createQuery("select p.personid, p.name from Person p order by p.personid desc ");
//集合中的元素不再是Person,而是一个Object[]对象数组
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//取每一行
Object[] row = ( Object[]) iterator.next();
//数组元素的顺序和查询时的参数顺序一样
int personid = Integer.parseInt(row[0].toString());
String PersonName = row[1].toString();
}
5.查询中使用构造器
EJB3 QL 支持将查询的属性结果直接作为一个java class 的构造器参数,并产生实体作为结果返回
例
//我们把需要的两个属性作为SimplePerson 的构造器参数,并使用new 函数。
Query query = em.createQuery("select new xxx.xxx.SimplePerson(p.name,p.sex) from Person p order by p.personid desc");
//集合中的元素是SimplePerson 对象
List result = query.getResultList();
6.聚合查询
和SQL 一样,如果聚合函数不是select...from 的唯一一个返回列,需要使用"GROUP BY"语句。"GROUP BY"应该包含select 语句中除了聚合函数外的所有属性,如果还需要加上查询条件,需要使用"HAVING"条件语句而不是"WHERE"语句
EJB3 QL 支持的聚合函数:
1. AVG() : select avg(p.age) from Person p
2. SUM() : select sum(p.age) from Person p
3. COUNT() : select count(p) from Person p
返回类型为Long,注意count(*)语法在hibernate 中可用,但在toplink 其它产品中并不可用
4. MAX() : select max(p.age) from Person p
5. MIN() : select min(p.age) from Person p
GROUP BY的例子:
//返回男女生各自的总人数
Query query = em.createQuery("select p.sex, count(p) from Person p group by p.sex");
//集合中的元素不再是Person,而是一个Object[]对象数组
List result = query.getResultList();
Iterator iterator = result.iterator();
while( iterator.hasNext() ){
//取每一行
Object[] row = (Object[]) iterator.next();
//数组中的第一个值是sex
boolean sex = Boolean.parseBoolean(row[0].toString());
//数组中的第二个值是聚合函数COUNT 返回值
String sextotal = row[1].toString();
}
HAVING例子
Query query = em.createQupery("select p.sex, count(p) from Person p group by p.sex having count(*)>?1");
7:关联
在EJB3 QL 中,仍然支持和SQL 中类似的关联语法:
left out join/left join
都是允许符合条件的右边表达式中的Entiies为空
//获取26 岁人的订单,不管Order 中是否有OrderItem
Query query = em.createQuery("select o from Order o left join o.orderItems where o.ower.age=26
order by o.orderid");
不加上left join也可以,需要显式使用left join/left outer join 的情况会比较少
inner join
右边的表达式必须返回Entities
//获取26 岁人的订单,Order 中必须要有OrderItem
Query query = em.createQuery("select o from Order o inner join o.orderItems where o.ower.age=26
order by o.orderid");
left join/inner join fetch
left/left out/inner join fetch 提供了一种灵活的查询加载方式来提高查询的性能。在默认的查询中,Entity 中的集合属性默认不会被关联,集合属性默认是缓加载( lazy-load ),这样的查询性能上有不足的地方。为了查询N 个Order,我们需要一条SQL 语句获得所有的Order 的原始对象属性, 但需要另外N 条语句获得每个Order 的orderItems 集合属性。为了避免N+1 的性能问题,我们可以利用join fetch 一次过用一条SQL 语句把Order 的所有信息查询出来.
//获取26 岁人的订单,Order 中必须要有OrderItem
Query query = em.createQuery("select o from Order o inner join fetch o.orderItems where
o.ower.age=26 order by o.orderid");
使用fetch,这个查询只会产生一条SQL 语句,比原来需要N+1 条SQL 语句在性能上有了极大的提升
8.排除相同的记录DISTINCT
使用关联查询,我们很经常得到重复的对象,如下面语句:
"select o from Order o inner join fetch o.orderItems order by o.orderid "
当有N 个orderItem 时就会产生N 个Order,而有些Order 对象往往是相同的
使用DISTINCT 关键字来排除掉相同的对象 :
Query query = em.createQuery("select DISTINCT o from Order o inner join fetch o.orderItems
order by o.orderid");
不同的Order对象只有一个
9.比较Entity
在查询中使用参数查询时,参数类型除了String, 原始数据类型( int, double 等)和它们的对象类型( Integer, Double等),也可以是Entity 的实例.
//查询某人的所有订单
<!-- Order的ower属性是一个Person对象 -->
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();
...
10.批量更新(Batch Update)
EJB3 QL 支持批量更新.
//把所有订单的金额加10
Query query = em.createQuery("update Order as o set o.amount=o.amount+10");
//update 的记录数
int result = query.executeUpdate();
11.批量删除(Batch Remove)
EJB3 QL 支持批量删除
//把金额小于100的订单删除,先删除订单子项,再删除订单
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");
int result = query.executeUpdate();//delete的记录数
...
12.使用操作符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);
List result = query.getResultList();
...
13.使用操作符BETWEEN
//查询金额在300 到1000 之间的订单
Query query = em.createQuery("select o from Order as o where o.amount between 300 and 1000");
List result = query.getResultList();
...
14.使用操作符IN
//查找年龄为26,21 的Person
Query query = em.createQuery("select p from Person as p where p.age in(26,21)");
List result = query.getResultList();
...
15.使用操作符LIKE
//查找以字符串"li"开头的Person
Query query = em.createQuery("select p from Person as p where p.name like 'li%'");
List result = query.getResultList();.
...
16.使用操作符IS NULL
//查询含有购买者的所有Order
Query query = em.createQuery("select o from Order as o where o.ower is not null order by
o.orderid");
List result = query.getResultList();
...
17.使用操作符IS EMPTY
IS EMPTY 是针对集合属性(Collection)的操作符.可以和NOT 一起使用
//查询含有订单项的所有Order
Query query = em.createQuery("select o from Order as o where o.orderItems is not empty order by
o.orderid");
List result = query.getResultList();
...
18.使用操作符EXISTS
[NOT]EXISTS 需要和子查询配合使用
//如果存在订单号为1 的订单,就获取所有OrderItem
Query query = em.createQuery("select oi from OrderItem as oi where exists (select o from Order o
where o.orderid=1)");
List result = query.getResultList();
...
19.字符串函数
EJB3 QL 定义了内置函数方便使用.这些函数的使用方法和SQL 中相应的函数方法类似.EJB3 QL 中定义的字符串函数包括:
1. CONCAT 字符串拼接
//查询所有人员,并在姓名后面加上字符串"_some"
Query query = em.createQuery("select p.personid, concat(p.name, '_some') from Person as p");
...
2. SUBSTRING 字符串截取
//查询所有人员,只取姓名的前三个字符
Query query = em.createQuery("select p.personid, substring(p.name,1,3) from Person as p");
...
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位
20.计算函数
EJB3 QL 中定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
//查询所有Order 的订单号及其总金额/10 的余数
Query query = em.createQuery("select o.orderid, mod(o.amount, 10) from Order as o");
...
SIZE 取集合的数量
//查询所有Order 的订单号及其订单项的数量
Query query = em.createQuery("select o.orderid, size(o.orderItems) from Order as o group by
o.orderid");
21.子查询
子查询可以用于WHERE 和HAVING 条件语句中
//查询年龄为26 岁的购买者的所有Order
Query query = em.createQuery("select o from Order as o where o.ower in(select p from Person as p
where p.age =26) order by o.orderid");
...
22.结果集分页
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页,QueryAPI 有两个接口方法可以解决这个问题:setMaxResults( ) 和setFirstResult( )
setMaxResults 方法设置获取多少条记录setFirstResult 方法设置从结果集中的那个索引开始获取(假如返回的记录有3 条,容器会自动为记录编上索引,索引从0 开始,依次为0,1,2)
例子:
Query query = em.createQuery("from Person p order by personid asc");
List list = query.setMaxResults(max).setFirstResult(index).getResultList();
em.clear();//分离内存中受EntityManager管理的实体bean,让VM进行垃圾回收
...
如果我们需要显示大量的实体Bean,假如记录成千上万,通过简单的循环处理,我们将很快消耗完内存,为此我们需要在显示了一部分实体bean 之后调用EntityManager.clear()及时把这些实体bean 从EntityManager 分离出来,让Java VM 对他们进行垃圾回收