•JPQL语言,即 Java Persistence Query Language 的简称。JPQL是一种和SQL非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的SQL查询,从而屏蔽不同数据库的差异。
•JPQL语言的语句可以是select 语句、update语句或delete语句,它们都通过 Query接口封装执行
•Query接口封装了执行数据库查询的相关方法。调用EntityManager的createQuery、createNamedQuery及createNativeQuery方法可以获得查询对象,进而可调用Query接口的相关方法来执行查询操作。
•Query接口的主要方法
–intexecuteUpdate()
•用于执行update或delete语句。
–List getResultList()
•用于执行select语句并返回结果集实体列表。
–Object getSingleResult()
•用于执行只返回单个结果实体的select语句。
–Query setFirstResult(intstartPosition)
•用于设置从哪个实体记录开始返回查询结果。
–Query setMaxResults(intmaxResult)
•用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询。
–Query setFlushMode(FlushModeTypeflushMode)
•设置查询对象的Flush模式。参数可以取2个枚举值:FlushModeType.AUTO为自动更新数据库记录,FlushModeType.COMMIT为直到提交事务时才更新数据库记录。
–setHint(StringhintName,Object value)
•设置与查询对象相关的特定供应商参数或提示信息。参数名及其取值需要参考特定JPA实现库提供商的文档。如果第二个参数无效将抛出IllegalArgumentException异常。
–setParameter(intposition, 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)
•为查询语句的指定位置参数赋Calendar值。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…andlikeinis null 等
–逻辑运算符: andor 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, intstart, intlength):取字串函数。
–trim([leading|trailing|both,][char c,] String s):从字符串中去掉首/尾指定的字符或空格。
–lower(String s):将字符串转换成小写形式。
–upper(String s):将字符串转换成大写形式。
–length(String s):求字符串的长度。
–locate(String s1, String s2[, intstart]):从第一个字符串中查找第二个字符串(子串)出现的位置。若未找到则返回0。
•算术函数主要有 abs、mod、sqrt、size等。Size用于求集合的元素个数。
•日期函数主要为三个,即current_date、current_time、current_timestamp,它们不需要参数,返回服务器上的当前日期、时间和时戳。