JPA - JPQL学习
JPQL语言,即 Java Persistence Query Language 的简称。JPQL 是一种和 SQL 非常类似的中间性和对象化查询语言,它最终会被编译成针对不同底层数据库的 SQL 查询,从而屏蔽不同数据库的差异。 JPQL语言的语句可以是 select 语句、update 语句或delete语句,它们都通过 Query 接口封装执行。
1、Query接口封装了执行数据库查询的相关方法。调用 EntityManager 的 createQuery、create NamedQuery 及 createNativeQuery 方法可以获得查询对象,进而可调用 Query 接口的相关方法来执行查询操作。
2、Query接口主要方法
- int executeUpdate():用于执行update或delete语句。
- List getResultList() :用于执行select语句并返回结果集实体列表。
- Object getSingleResult() 用于执行只返回单个结果实体的select语句。
- Query setFirstResult(int startPosition) 用于设置从哪个实体记录开始返回查询结果。
- Query setMaxResults(int maxResult) 用于设置返回结果实体的最大数。与setFirstResult结合使用可实现分页查询。
- 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 异常。
3,其实除了上面这些方法外,JPQL和一般的sql也没有什么区别了。
SELECT语句:select o from VO o;查询语句就需要注意几点,第一,VO值得是这个实体类,还有就是涉及到条件的时候,字段都是vo的属性,而不是数据表中的字段。
@Test public void testJPQL(){ String sql="select o from User o where id=?1"; Query query=em.createQuery(sql); query.setParameter(1, 1); List<User> users=query.getResultList(); for(User u:users){ System.out.println(u.getName()); } }
WHERE:
where子句用于指定查询条件,where跟条件表达式。例: select o from Orders o where o.id = 1 select o from Orders o where o.id > 3 and o.confirm = 'true' select o from Orders o where o.address.streetNumber >= 123 JPQL也支持包含参数的查询,例如: select o from Orders o where o.id = :myId select o from Orders o where o.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 之间的订单。 select o from Orders o where o.id between 100 and 200 // 以下语句查询国籍为的 'US'、'CN'或'JP' 的客户。 select c from Customers c where c.county in ('US','CN','JP') // 以下语句查询手机号以139开头的客户。%表示任意多个字符序列,包括0个。 select c from Customers c where c.phone like '139%' // 以下语句查询名字包含4个字符,且234位为ose的客户。_表示任意单个字符。 select c from Customers c where c.lname like '_ose' // 以下语句查询电话号码未知的客户。Nul l用于测试单值是否为空。 select c from Customers c where c.phone is null // 以下语句查询尚未输入订单项的订单。empty用于测试集合是否为空。 select o from Orders o where o.orderItems is empty
查询部分属性:
如果只须查询实体的部分属性而不需要返回整个实体。例如: select o.id, o.customerName, o.address.streetNumber from Order o order by o.id 执行该查询返回的不再是Orders实体集合,而是一个对象数组的集合(Object[]),集合的每个成员为一个对象数组,可通过数组元素访问各个属性。
/** * 使用查询缓存 */ String sql="select 0 from User o"; Query query=em.createQuery(sql); query.setHint(QueryHints.CACHEABLE, false);
order by子句:order by子句用于对查询结果集进行排序。和SQL的用法类似,可以用 “asc“ 和 "desc“ 指定升降序。如果不显式注明,默认为升序。 select o from Orders o order by o.id select o from Orders o order by o.address.streetNumber desc select o from Orders o order by o.customer asc, o.id desc
group by子句与聚合查询:group by 子句用于对查询结果分组统计,通常需要使用聚合函数。常用的聚合函数主要有 AVG、SUM、COUNT、MAX、MIN 等,它们的含义与SQL相同。例如: select max(o.id) from Orders o 没有 group by 子句的查询是基于整个实体类的,使用聚合函数将返回单个结果值,可以使用Query.getSingleResult()得到查询结果。例如: Query query = entityManager.createQuery( "select max(o.id) from Orders o"); Object result = query.getSingleResult(); Long max = (Long)result; … …
having子句:Having 子句用于对 group by 分组设置约束条件,用法与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)查询。例如: select o from Orders o where o.address.streetNumber=2000 上述JPQL语句编译成以下SQL时就会自动包含关联,默认为左关联。 在某些情况下可能仍然需要对关联做精确的控制。为此,JPQL 也支持和 SQL 中类似的关联语法。如: left out join / left join inner join left join / inner join fetch 其中,left join和left out join等义,都是允许符合条件的右边表达式中的实体为空。
子查询:JPQL也支持子查询,在 where 或 having 子句中可以包含另一个查询。当子查询返回多于 1 个结果集时,它常出现在 any、all、exist s表达式中用于集合匹配查询。它们的用法与SQL语句基本相同.
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,它们不需要参数,返回服务器上的当前日期、时间和时戳
update语句:update语句用于执行数据更新操作。主要用于针对单个实体类的批量更新 以下语句将帐户余额不足万元的客户状态设置为未偿付: update Customers c set c.status = '未偿付' where c.balance < 10000
delete语句:delete语句用于执行数据更新操作。 以下语句删除不活跃的、没有订单的客户: delete from Customers c where c.status = 'inactive' and c.orders is empty