`
13594135
  • 浏览: 190494 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

JPQL的一些用法

    博客分类:
  • ejb
阅读更多
关联(join)
JPQL仍然支持和SQL中类似的关联语法:
left out join/left join
inner join
left join fetch/inner join fetch


left out join/left join等,都是允许符合条件的右边表达式中的Entiies 为空(需要显式使用left join/left outer join 的情况会比较少。)
例:
//获取26岁人的订单,不管Order中是否有OrderItem
select o from Order o left join o.orderItems where o.ower.age=26 order by o.orderid


inner join 要求右边的表达式必须返回Entities。
例:
//获取26 岁人的订单,Order 中必须要有OrderItem
select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid


!!重要知识点:在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载( lazy-load )。那么,left fetch/left out fetch/inner join fetch提供了一种灵活的查询加载方式来提高查询的性能。
例:
private String QueryInnerJoinLazyLoad(){
// 默认不关联集合属性变量(orderItems)对应的表
Query query = em.createQuery("select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid");
List result = query.getResultList();
if (result!=null && result.size()>0){
//这时获得Order 实体中orderItems( 集合属性变量)为空
Order order = (Order) result.get(0);
//当需要时,EJB3 Runtime才会执行一条SQL语句来加载属于当前Order的
//OrderItems
Set<OrderItem> list = order.getOrderItems();
Iterator<OrderItem> iterator = list.iterator();
if (iterator.hasNext()){
OrderItem orderItem =iterator.next();
System.out.println ("订购产品名:"+ orderItem.getProductname());
}
}

上面代码在执行"select o from Order o inner join o.orderItems where o.ower.age=26 order by o.orderid"时编译成的SQL如下(他不包含集合属性变量(orderItems)对应表的字段):
select order0_.orderid as orderid6_, order0_.amount as amount6_, order0_.person_id as
person4_6_, order0_.createdate as createdate6_ from Orders order0_ inner join OrderItems
orderitems1_ on order0_.orderid=orderitems1_.order_id, Person person2_ where
order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid


上面代码当执行到Set<OrderItem> list = order.getOrderItems();时才会执行一条SQL语句来加载属于当前Order的OrderItems,编译成的SQL 如下:
select orderitems0_.order_id as order4_1_, orderitems0_.id as id1_, orderitems0_.id as id7_0_,
orderitems0_.order_id as order4_7_0_, orderitems0_.productname as productn2_7_0_,
orderitems0_.price as price7_0_ from OrderItems orderitems0_ where orderitems0_.order_id=?
order by orderitems0_.id ASC

这样的查询性能上有不足的地方。为了查询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");

上面这句HPQL编译成以下的SQL:
select order0_.orderid as orderid18_0_, orderitems1_.id as id19_1_, order0_.amount as
amount18_0_,order0_.person_id as person4_18_0_, order0_.createdate as createdate18_0_,
orderitems1_.order_id as order4_19_1_, orderitems1_.productname as productn2_19_1_,
orderitems1_.price as price19_1_, orderitems1_.order_id as order4_0__, orderitems1_.id as id0__
from Orders order0_ inner join OrderItems orderitems1_ on
order0_.orderid=orderitems1_.order_id, Person person2_ where
order0_.person_id=person2_.personid and person2_.age=26 order by order0_.orderid,
orderitems1_.id ASC

上面由于使用了fetch,这个查询只会产生一条SQL语句,比原来需要N+1 条SQL语句在性能上有了极大的提升


排除相同的记录DISTINCT
使用关联查询,我们很经常得到重复的对象,如下面语句:
"select o from Order o inner join fetch o.orderItems order by o.orderid "
当有N 个orderItem 时就会产生N个Order,而有些Order对象往往是相同的,这时我们需要使用DISTINCT关键字来排除掉相同的对象。
例:
select DISTINCT o from Order o inner join fetch o.orderItems order by o.orderid



比较Entity
在查询中使用参数查询时,参数类型除了String, 原始数据类型( int, double等)和它们的对象类型( Integer, Double等),也可以是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);


批量更新(Batch Update)
HPQL支持批量更新
例:
//把所有订单的金额加10
Query query = em.createQuery("update Order as o set o.amount=o.amount+10");
//update 的记录数
int result = query.executeUpdate();


批量删除(Batch Remove)
例:
//把金额小于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");
query.executeUpdate();//delete的记录数


使用操作符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);


使用操作符BETWEEN
select o from Order as o where o.amount between 300 and 1000

使用操作符IN
//查找年龄为26,21 的Person
select p from Person as p where p.age in(26,21)

使用操作符LIKE
//查找以字符串"li"开头的Person
select p from Person as p where p.name like 'li%'

使用操作符IS NULL
//查询含有购买者的所有Order
select o from Order as o where o.ower is [not] null

使用操作符IS EMPTY
IS EMPTY是针对集合属性(Collection)的操作符。可以和NOT 一起使用。注:低版权的Mysql 不支持IS EMPTY
//查询含有订单项的所有Order
select o from Order as o where o.orderItems is [not] empty

使用操作符EXISTS
[NOT]EXISTS 需要和子查询配合使用。注:低版权的Mysql 不支持EXISTS
//如果存在订单号为1 的订单,就获取所有OrderItem
select oi from OrderItem as oi where exists (select o from Order o where o.orderid=1)
//如果不存在订单号为10 的订单,就获取id 为1 的OrderItem
select oi from OrderItem as oi where oi.id=1 and not exists (select o from Order o where o.orderid=10)


字符串函数
JPQL定义了内置函数方便使用。这些函数的使用方法和SQL中相应的函数方法类似。包括:
1. CONCAT 字符串拼接
2. SUBSTRING 字符串截取
3. TRIM 去掉空格
4. LOWER 转换成小写
5. UPPER 装换成大写
6. LENGTH 字符串长度
7. LOCATE 字符串定位

例:
//查询所有人员,并在姓名后面加上字符串"_foshan"
select p.personid, concat(p.name, '_foshan') from Person as p
//查询所有人员,只取姓名的前三个字符
select p.personid, substring(p.name,1,3) from Person as p

计算函数
HPQL定义的计算函数包括:
ABS 绝对值
SQRT 平方根
MOD 取余数
SIZE 取集合的数量

例:
//查询所有Order 的订单号及其订单项的数量
select o.orderid, size(o.orderItems) from Order as o group by o.orderid
//查询所有Order 的订单号及其总金额/10 的余数
select o.orderid, mod(o.amount, 10) from Order as o


子查询
子查询可以用于WHERE 和HAVING 条件语句中
例:
//查询年龄为26 岁的购买者的所有Order
select o from Order as o where o.ower in(select p from Person as p where p.age =26)


结果集分页
有些时候当执行一个查询会返回成千上万条记录,事实上我们只需要显示一部分数据。这时我们需要对结果集进行分页,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;
}
}
来源:(http://blog.sina.com.cn/s/blog_6262bed30100gsjg.html) - EJB3 JPA JPQL 语句 查询 使用 函数 分页 子查询(2)_花籽的泪_新浪博客
分享到:
评论

相关推荐

    EJB3.0查询语句JPQL用法

    EJB3.0查询语句JPQL用法 PQL 和 SQL 有很多相似之处。归根结底,它们都用于访问和操作数据库数据。而且,二者都使用非过程语句 — 通过特殊解释程序识别的命令。此外,JPQL 在语法上与 SQL 也相似。 JPQL 和 SQL 的...

    基于JPQL实现纯SQL语句方法详解

    基于首次在EJB2.0中引入的EJB查询语言(EJB QL),Java持久化查询语言(JPQL)是一种可移植的查询语言,旨在以面向对象表达式语言的表达式,将SQL语法和简单查询语义绑定在一起·使用这种语言编写的查询是可移植的,可以...

    EntityMatcher:通过匹配的实体类创建JPQL查询

    可以使用Entities属性的名称来创建匹配器,也可以使用方便地准备以捕获方法调用的实体匹配“模拟”来创建匹配器。 这个WHERE陈述... WHERE person.name LIKE 'X%' OR person.surname LIKE 'Y%' OR person.eyes = '...

    使用Spring Data Jpa为我们提供的@EntityGraph.docx

    在很多情况下,我们使用Spring-Data- Jpa,一些简单的查询,我们都喜欢用定义方法查询,而不是写JPQL。JPA为我们提供了一组注解:使用Spring-Data- Jpa为我们提供的@EntityGraph,或@EntityGraph和@NamedEntityGraph...

    spring date jpa

    Spring整合Spring Data JPA 的使用,包括三种的查询方式 借助接口中的定义好的方法完成查询 jpql的查询方式 方法名称规则查询

    优秀实践分享 Spring Data JPA2

    JPA 使用@Query注解实现JPQL和本地自定义查询 JPA API 条件查询 (子查询,多表连接查询) JPA结合QueryDSL轻松完成复杂查询(自连接,多表连接查询) 参与文档: Pro JPA2中文版:精通Java持久化API 优秀博文读书笔记: ...

    jpa复杂查询,映射DTO,自动映射无需关注类型,不用建构造函数

    jpa复杂查询,映射到具体的DTO上就比较复杂,需要类型完全匹配,还要求要建造构造函数,而且只能使用jpql查询,非常麻烦,querydsl也不方便,代码太长,后期维护的时候看上去也不直观。复杂sql还是采用原生sql比较...

    JSF2datatable分页控件与左侧菜单

    下面帖我的控件的使用方法:  下载地址:http://download.csdn.net/detail/ptianfeng/4802713 一、分页具体使用方法如下(不多说,直接给你些颜色看看): 1. xhtml文件:   &lt;html xmlns:ems=...

    论坛:由Spring Framework和MySQL支持的Internet论坛[2017]

    论坛 描述 由Spring Framework和MySQL支持的Internet论坛... 从JpaRepository使用JPQL和现成的方法来创建,读取,更新和删除数据 本地查询的实现 Spring安全: 拥有基于数据库的用户身份验证的自己的登录表单 限制离

    一个EAR项目 在身份证验证会话Bean的基础上定义本地接口,接口包含查询身份证所在省市、地区的商业方法,并利用Web页面测试

    将部分地区代码存入到JavaDB数据库中,所需的表结构自行设计,在会话Bean中通过使用JPQL实现地区代码的查询。 (3)会话Bean组件新增的本地接口及查询商业方法的名称、参数以及返回值请按照题目要求自行确定。 (4...

    dropwizard-example-bazel:使用 Bazel 构建的 Dropwizard 示例

    提供的示例说明了可用的一些功能,并演示了如何在 Dropwizard 中使用这些功能。 此数据库示例由以下类组成: PersonDAO说明了在 Hibernate 的帮助下使用数据访问对象模式。 Person说明了在 JPA 注释的帮助下将 Java...

    dropwizard-template:一个简单的 dropwizard 项目模板

    提供的示例说明了可用的一些功能,并演示了如何在 Dropwizard 中使用这些功能。 此数据库示例由以下类组成: PersonDAO说明了在 Hibernate 的帮助下使用数据访问对象模式。 Person说明了在 JPA 注释的帮助下将 ...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    3.6.5 使用托管Bean的方法执行校验 173 3.6.6 绑定到Bean属性的校验器 175 3.7 本章小结 177 第4章 利用JDBC和JTA访问 数据库和管理全局事务 178 4.1 JDBC和容器管理的数据源 179 4.1.1 JDBC概述 179 4.1.2 使用JDBC...

    jpa-examples

    注入由@PersistenceContext注释使用强制执行,因为 JPA 版本 1.0(直到当前 2.1)可以在TYPE (类)、方法(setter)或FIELD (实体管理器字段本身)上使用,但不能与构造器。 此示例为这种情况提供了解决方法,在...

    支持多数据库的ORM框架ef-orm.zip

    大部分OLTP应用系统到最后都不免要使用SQL/JPQL,然而没有一个很好的方法解决SQL在多种数据库下兼容性的问题。 EF-ORM中采用了独特的SQL解析和改写技术,能够主动检查并确保SQL语句或者SQL片段在各个数据库上的兼容...

    weedow-searchy:使用强大的查询语言通过HTTP自动公开Web服务以搜索与实体相关的数据

    Searchy提供了一种高级搜索引擎,该引擎不需要使用在实体的不同字段上进行搜索所需的自定义方法来创建存储库。 我们可以在任何字段上搜索,组合多个条件以优化搜索,甚至可以搜索嵌套字段。为什么要使用Searchy? ...

    JSF2.xdatatable分页控件与左侧菜单最简单应用

    一、分页具体使用方法如下(不多说,直接给你些颜色看看): 1. xhtml文件:   &lt;html xmlns:ems="http://www.ems.com.cn" xmlns:h="http://java.sun.com/jsf/html" xmlns:f="http://java.sun.com/jsf/core"...

    EventTrackerProject

    对于这个特定的项目,我创建了一个Spring Boot应用程序,该应用程序允许用户跟踪他们的费用,包括交易的类别和使用的付款方式。 Spring Data JPA用于简化API的编码,因此不需要显式的EntityManager对象或JPQL查询。...

    blaze-domain

    最后,这允许使用简化的DSL和自定义域模型对表达式或谓词进行建模,并可以将其转换为JPQL.Next表达式将通过Blaze-Persistence进行使用。特征Blaze-Domain支持具有属性的结构化类型(实体)的定义定制功能的定义...

    play framework 框架手册 word 版

    使用JPQL 查询进行查找 - 74 - Counting统计对象 - 74 - 用play.db.jpa.Blob存储上传文件 - 74 - 强制保存 - 75 - 更多公共类型generic typing问题 - 77 - 08.Play.libs库包 - 78 - 用XPath解析XML - 78 - Web ...

Global site tag (gtag.js) - Google Analytics