JPQL的一些用法

来源:互联网 发布:广联达预算软件盗版 编辑:程序博客网 时间:2024/06/16 04:58
关联(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;  }  }
0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 八宝粥的拉环断了怎么办 八宝粥易拉罐拉环断了怎么办 吃完辣的胃难受怎么办 天天呆在家很烦怎么办 吃多了荔枝上火怎么办 猛犸牙牌子裂了怎么办 玩游戏电脑卡了怎么办 电脑打开卡在选项界面怎么办? 红警突然卡死怎么办 柯基不吃狗粮怎么办 貔貅嘴巴磕破了怎么办 开光貔貅牙磕了怎么办 玉貔貅鼻子碎了怎么办 开光的貔貅摔坏了怎么办 貔貅摔坏了耳朵怎么办? 貔貅摔坏了一点点怎么办 天猫删评价扣4分怎么办 暴风影音下载电视剧下载不了怎么办 fm2017引援电脑买了怎么办 退休时医保不够二十年怎么办 和的面迟迟不发怎么办 做面条的面发了怎么办 发不起来的面团怎么办 如果婚后买房离婚后财产怎么办 空腹体检前喝水了怎么办 莆田市风俗婴儿死了怎么办后事 上司给你换不好岗位怎么办 领导要把我调走怎么办 美国上庭遇法官退休案子怎么办 夫妻一套房离婚户囗怎么办 正营生不了副团怎么办 浅色衣服被染色了怎么办 解大便解不出来怎么办 强拆挖掘机被村民扣押怎么办 小孩哭的时候接不上气怎么办 昆明市长信箱发不出去怎么办 中国公民在香港想去澳门怎么办 面包车不给贴膜怎么办 在香港海关被扣怎么办 发现被医院骗了怎么办 白皮子科染上血怎么办