•
JPQL
语言,即
Java Persistence Query Language
的简称。
JPQL
是一种和
SQL
非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的
SQL
查询,从而屏蔽不同数据库的差异。
•
JPQL
语言的语句可以是
select
语句、
update
语句或
delete
语句,它们都
通过
Query
接口封装执行
•
Query
接口
封装了执行数据库查询的相关方法。调用
EntityManager
的
createQuery
、
create
NamedQuery
及
createNativeQuery
方法可以获得查询对象,进而可调用
Query
接口的相关方法来执行查询操作。
•
Query
接口的主要方法
–
int
executeUpdate
()
•
用于执行
update
或
delete
语句。
–
List
getResultList
()
•
用于执行
select
语句并返回结果集实体列表。
–
Object
getSingleResult
()
•
用于执行只返回单个结果实体的
select
语句。
–
Query
setFirstResult
(
int
startPosition
)
•
用于设置从哪个实体记录开始返回查询
结果。
–
Query
setMaxResults
(
int
maxResult
)
•
用于设置返回结果实体的最大数
。
与
setFirstResult
结合使用可实现分页查询
。
–
Query
setFlushMode
(
FlushModeType
flushMode
)
•
设置查询对象的
Flush
模式。参数可以取
2
个枚举值:
FlushModeType.AUTO
为
自动更新数据库记录,
FlushMode
Type.COMMIT
为
直到提交事务时才更新数据库记录。
–
setHint
(String
hintName
,Object value)
•
设置与查询对象相关的特定供应商参数或提示信息
。参数名及其取值需要参考特定
JPA
实现库提供商的文档。如果第二个参数无效将抛出
IllegalArgumentException
异常。
–
setParameter
(
int
position, Object value)
•
为查询语句的指定位置参数赋值。
Position
指定参数序号,
value
为赋给参数的值。
–
setParameter
(
int
position, Date d,
TemporalType
type)
•
为查询语句的指定位置参数赋
Date
值。
Position
指定参数序号,
value
为赋给参数的值,
temporalType
取
TemporalType
的枚举常量,包括
DATE
、
TIME
及
TIMESTAMP
三个,,用于将
Java
的
Date
型值临时转换为数据库支持的日期时间类型(
java.sql.Date
、
java.sql.Time
及
java.sql.Timestamp
)。
–
setParameter
(
int
position, Calendar c,
TemporalType
type)
•
为查询语句的指定位置参数赋
Calenda
r
值。
position
指定参数序号,
value
为赋给参数的值,
temporalType
的含义及取舍同前。
–
setParameter
(String name, Object value)
•
为查询语句的指定名称参数赋值。
–
setParameter
(String name, Date d,
TemporalType
type)
•
为查询语句的指定名称参数赋
Date
值。用法同前。
–
setParameter
(String name, Calendar c,
TemporalType
type)
•
为查询语句的指定名称参数设置
Calendar
值。
name
为参数名,其它同前。该方法调用时如果参数位置或参数名不正确,或者所赋的参数值类型不匹配,将抛出
IllegalArgumentException
异常。
•
查询所有实体的
JPQL
查询字串很简单,例如:
selecto from Order o或 selecto from Order as o
•
关键字
as
可以省去。
•标识符变量的命名规范与 Java标识符相同,且区分大小写。
•
where
子句用于指定查询条件,
where
跟条件表达式。例:
selecto from Orders o where o.id = 1
select o from Orders o whereo.id > 3 and o.confirm = 'true'
select o from Orders o where o.address.streetNumber >=123
•
JPQL
也支持包含参数的查询,例如:
selecto from Orders o where o.id = :myId
select o from Orders o whereo.id = :myId and o.customer = :customerName
注意:参数名前必须冠以冒号(:),执行查询前须使用Query.setParameter(name,value)方法给参数赋值。
•
也可以不使用参数名而使用参数的
序号
,例如:
select o from Order o where o.id = ?1 and o.customer = ?2
–
其中
?1
代表第一个参数,
?2
代表第一个参数。在执行查询之前需要使用重载方法
Query.setParameter
(
pos
,value)
提供参数值。
Query query = entityManager.createQuery( "select o from Orders o where o.id = ?1 and o.customer = ?2" );
query.setParameter( 1, 2 );
query.setParameter( 2, "John" );
List orders = query.getResultList();
… …
•
where
条件表达式中可用的运算符基本上与
SQL
一致,包括:
–
算术运算符:
+
-
*
/
+
(
正
)
-
(
负
)
–
关系运算符:
==
<>
>
>=
<
<=
between…and
like
in
is null
等
–
逻辑运算符:
and
or
not
•
下面是一些
常见查询表达式
示例:
// 以下语句查询Id介于100至200之间的订单。
selecto from Orders o where o.id between 100 and 200
// 以下语句查询国籍为的'US'、'CN'或'JP'的客户。
selectc from Customers c where c.county in ('US','CN','JP')
// 以下语句查询手机号以139开头的客户。%表示任意多个字符序列,包括0个。
selectc from Customers c where c.phone like '139%'
// 以下语句查询名字包含4个字符,且234位为ose的客户。_表示任意单个字符。
selectc from Customers c where c.lname like '_ose'
// 以下语句查询电话号码未知的客户。Null用于测试单值是否为空。
selectc from Customers c where c.phone is null
// 以下语句查询尚未输入订单项的订单。empty用于测试集合是否为空。
selecto from Orders o where o.orderItems is empty
•
如果只须查询实体的部分属性而不需要返回整个实体。例如:
selecto.id, o.customerName, o.address.streetNumber from Order o order by o.id
•
执行该查询返回的不再是
Orders
实体集合,而是一个
对象数组的集合
(Object[])
,集合的每个成员为一个对象数组,可通过数组元素访问各个属性。
group by子句与聚合查询
•
group by
子句用于对查询结果分组统计,通常需要使用
聚合函数
。常用的聚合函数主要有
AVG
、
SUM
、
COUNT
、
MAX
、
MIN
等,它们的含义与
SQL
相同。例如:
select max(o.id) from Orders o
•
没有
groupby
子句的查询是基于整个实体类的,使用聚合函数将返回单个结果值,可以使用
Query.getSingleResult
()
得到查询结果。例如:
Query query = entityManager.createQuery(
"select max(o.id) fromOrders o");
Object result = query.getSingleResult();
Long max = (Long)result;
… …
•
Having
子句用于对
groupby
分组设置约束条件,用法与
where
子句基本相同,不同是
where
子句作用于基表或视图,以便从中选择满足条件的记录;
having
子句则作用于分组,
用于选择满足条件的组,其条件表达式中通常会使用聚合函数
。
•
例如,以下语句用于查询订购总数大于
100
的商家所售商品及数量:
select o.seller, o.goodId, sum(o.amount) from V_Orders o group by
o.seller, o.goodId having sum(o.amount) > 100
•
having
子句与
where
子句一样都可以使用参数。
关联查询
•
在
JPQL
中,很多时候都是通过在实体类中配置实体关联的类属性来实现隐含的关联
(join)
查询。例如:
selecto from Orders o where o.address.streetNumber=2000
•
上述
JPQL
语句编译成以下
SQL
时就会自动包含关联,默认为左关联。
•
在某些情况下可能仍然需要对关联做精确的控制。为此,
JPQL
也支持和
SQL
中类似的关联语法。如:
–
left out join / left join
–
inner join
–
left join / inner join fetch
–
其中,
leftjoin
和
leftout join
等义,都是允许符合条件的右边表达式中的实体为空。
JPQL函数
•
JPQL
提供了以下一些内建函数,包括字符串处理函数、算术函数和日期函数。
•
字符串处理函数
主要有:
–
concat
(String s1, String s2)
:字符串合并
/
连接函数。
–
substring
(String s,
int
start,
int
length)
:取字串函数。
–
trim
([
leading|trailing|both
,][char c,] String s)
:从字符串中去掉首
/
尾指定的字符或空格。
–
lower
(String s)
:将字符串转换成小写形式。
–
upper
(String s)
:将字符串转换成大写形式。
–
length
(String s)
:求字符串的长度。
–
locate
(String s1, String s2[,
int
start])
:从第一个字符串中查找第二个字符串
(
子串
)
出现的位置。若未找到则返回
0
。
•
算术函数
主要有
abs
、
mod
、
sqrt
、
size
等。
Size
用于求集合的元素个数。
•
日期函数
主要为三个,即
current_date
、
current_time
、
current_timestamp
,它们不需要参数,返回服务器上的当前日期、时间和时戳。