jpql查询Word下载.docx
- 文档编号:970773
- 上传时间:2023-04-29
- 格式:DOCX
- 页数:17
- 大小:20.79KB
jpql查询Word下载.docx
《jpql查询Word下载.docx》由会员分享,可在线阅读,更多相关《jpql查询Word下载.docx(17页珍藏版)》请在冰点文库上搜索。
//命名参数查询时使用,参数类型为java.util.Date
QuerysetParameter(Stringname,java.util.Datevalue,TemporalTypetemporalType);
//命名参数查询时使用,参数类型为java.util.Calendar
QuerysetParameter(Stringname,Calendarvalue,TemporalTypetemporalType);
//位置参数查询时使用,参数类型为java.util.Date
QuerysetParameter(intposition,Datevalue,TemporalTypetemporalType);
//位置参数查询时使用,参数类型为java.util.Calendar
QuerysetParameter(intposition,Calendarvalue,TemporalTypetemporalType);
}
因为一个Date或Calendar对象能够描述一个真实的日期、时间或时间戳.所以我们需要告诉Query对象怎么使用这些参数,我们把javax.persistence.TemporalType作为参数传递进setParameter方法,告诉查询接口在转换java.util.Date或java.util.Calendar参数到本地SQL时使用什么数据库类型。
下面通过实例来学习JPQL语句,例子的entityBean有Person,Order,OrderItem,他们之间的关系是:
一个Person有多个Order,一个Order有多个OrderItem。
JPQL语句的大小写敏感性:
除了Java类和属性名称外,查询都是大小写不敏感的。
所以,SeLeCT和sELEct以及SELECT相同的,但是com.foshanshop.ejb3.bean.Person和com.foshanshop.ejb3.bean.PERSon是不同的,person.name和person.NAME也是不同的。
命名查询
可以在实体bean上通过@NamedQueryor@NamedQueries预先定义一个或多个查询语句,减少每次因书写错误而引起的BUG。
通常把经常使用的查询语句定义成命名查询。
定义单个命名查询:
@NamedQuery(name="
getPerson"
query="
FROMPersonWHEREpersonid=?
)
@Entity
publicclassPersonimplementsSerializable{
如果要定义多个命名查询,应在@javax.persistence.NamedQueries里定义@NamedQuery:
@NamedQueries({
),
getPersonList"
FROMPersonWHEREage>
?
})
当命名查询定义好了之后,我们就可以通过名称执行其查询。
代码如下:
Queryquery=em.createNamedQuery("
query.setParameter(1,1);
排序(orderby)
"
ASC"
和"
DESC"
分别为升序和降序,JPQL中默认为asc升序
//先按年龄降序排序,然后按出生日期升序排序
selectpfromPersonporderbyp.agedesc,p.birthdayasc"
查询部分属性
通常来说,都是针对Entity类的查询,返回的也是被查询的Entity类的实体。
JPQL也允许我们直接查询返回我们需要的属性,而不是返回整个Entity。
在一些Entity中属性特别多的情况,这样的查询可以提高性能
//只查询我们感兴趣的属性(列)
Queryquery=em.createQuery("
selectp.personid,p.namefromPersonporderbyp.personiddesc"
//集合中的元素不再是Person,而是一个Object[]对象数组
Listresult=query.getResultList();
if(result!
=null){
Iteratoriterator=result.iterator();
while(iterator.hasNext()){
Object[]row=(Object[])iterator.next();
intpersonid=Integer.parseInt(row[0].toString());
StringPersonName=row[1].toString();
查询中使用构造器(Constructor)
JPQL支持将查询的属性结果直接作为一个javaclass的构造器参数,并产生实体作为结果返回。
例如上面的例子只获取personentitybean的nameandpersonid属性,我们不希望返回的集合的元素是object[],而希望用一个类来包装它。
就要用到使用构造器。
publicclassSimplePerson{
privateIntegerpersonid;
privateStringname;
。
publicSimplePerson(){
publicSimplePerson(Integerpersonid,Stringname){
this.name=name;
this.personid=personid;
查询代码为:
//我们把需要的两个属性作为SimplePerson的构造器参数,并使用new函数。
selectnewcom.foshanshop.ejb3.bean.SimplePerson(p.personid,p.name)fromPersonporderbyp.personiddesc"
//集合中的元素是SimplePerson对象
SimplePersonsimpleperson=(SimplePerson)iterator.next();
聚合查询(Aggregation)
JPQL支持的聚合函数包括:
1.AVG()
2.SUM()
3.COUNT(),返回类型为Long,注意count(*)语法在hibernate中可用,但在toplink其它产品中并不可用
4.MAX()
5.MIN()
//获取最大年龄
selectmax(p.age)fromPersonp"
Objectresult=query.getSingleResult();
StringmaxAge=result.toString();
//获取平均年龄
query=em.createQuery("
selectavg(p.age)fromPersonp"
//获取最小年龄
selectmin(p.age)fromPersonp"
//获取总人数
selectcount(p)fromPersonp"
//获取年龄总和
selectsum(p.age)fromPersonp"
如果聚合函数不是select...from的唯一一个返回列,需要使用"
GROUPBY"
语句。
应该包含select语句中除了聚合函数外的所有属性。
//返回男女生各自的总人数
selectp.sex,count(p)fromPersonpgroupbyp.sex"
如果还需要加上查询条件,需要使用"
HAVING"
条件语句而不是"
WHERE"
语句
//返回人数超过1人的性别
selectp.sex,count(p)fromPersonpgroupbyp.sexhavingcount(*)>
//设置查询中的参数
query.setParameter(1,newLong
(1));
关联(join)
JPQL仍然支持和SQL中类似的关联语法:
leftoutjoin/leftjoin
innerjoin
leftjoinfetch/innerjoinfetch
leftoutjoin/leftjoin等,都是允许符合条件的右边表达式中的Entiies为空(需要显式使用leftjoin/leftouterjoin的情况会比较少。
//获取26岁人的订单,不管Order中是否有OrderItem
selectofromOrderoleftjoino.orderItemswhereo.ower.age=26orderbyo.orderid
innerjoin要求右边的表达式必须返回Entities。
//获取26岁人的订单,Order中必须要有OrderItem
selectofromOrderoinnerjoino.orderItemswhereo.ower.age=26orderbyo.orderid
!
重要知识点:
在默认的查询中,Entity中的集合属性默认不会被关联,集合属性默认是延迟加载(lazy-load)。
那么,leftfetch/leftoutfetch/innerjoinfetch提供了一种灵活的查询加载方式来提高查询的性能。
privateStringQueryInnerJoinLazyLoad(){
//默认不关联集合属性变量(orderItems)对应的表
selectofromOrderoinnerjoino.orderItemswhereo.ower.age=26orderbyo.orderid"
=null&
&
result.size()>
0){
//这时获得Order实体中orderItems(集合属性变量)为空
Orderorder=(Order)result.get(0);
//当需要时,EJB3Runtime才会执行一条SQL语句来加载属于当前Order的
//OrderItems
Set<
OrderItem>
list=order.getOrderItems();
Iterator<
iterator=list.iterator();
if(iterator.hasNext()){
OrderItemorderItem=iterator.next();
System.out.println("
订购产品名:
+orderItem.getProductname());
上面代码在执行"
时编译成的SQL如下(他不包含集合属性变量(orderItems)对应表的字段):
selectorder0_.orderidasorderid6_,order0_.amountasamount6_,order0_.person_idas
person4_6_,order0_.createdateascreatedate6_fromOrdersorder0_innerjoinOrderItems
orderitems1_onorder0_.orderid=orderitems1_.order_id,Personperson2_where
order0_.person_id=person2_.personidandperson2_.age=26orderbyorder0_.orderid
上面代码当执行到Set<
时才会执行一条SQL语句来加载属于当前Order的OrderItems,编译成的SQL如下:
selectorderitems0_.order_idasorder4_1_,orderitems0_.idasid1_,orderitems0_.idasid7_0_,
orderitems0_.order_idasorder4_7_0_,orderitems0_.productnameasproductn2_7_0_,
orderitems0_.priceasprice7_0_fromOrderItemsorderitems0_whereorderitems0_.order_id=?
orderbyorderitems0_.idASC
这样的查询性能上有不足的地方。
为了查询N个Order,我们需要一条SQL语句获得所有的Order的原始对象属性,但需要另外N条语句获得每个Order的orderItems集合属性。
为了避免N+1的性能问题,我们可以利用joinfetch一次过用一条SQL语句把Order的所有信息查询出来
例子
selectofromOrderoinnerjoinfetcho.orderItemswhere
o.ower.age=26orderbyo.orderid"
上面这句HPQL编译成以下的SQL:
selectorder0_.orderidasorderid18_0_,orderitems1_.idasid19_1_,order0_.amountas
amount18_0_,order0_.person_idasperson4_18_0_,order0_.createdateascreatedate18_0_,
orderitems1_.order_idasorder4_19_1_,orderitems1_.productnameasproductn2_19_1_,
orderitems1_.priceasprice19_1_,orderitems1_.order_idasorder4_0__,orderitems1_.idasid0__
fromOrdersorder0_innerjoinOrderItemsorderitems1_on
order0_.orderid=orderitems1_.order_id,Personperson2_where
order0_.person_id=person2_.personidandperson2_.age=26orderbyorder0_.orderid,
orderitems1_.idASC
上面由于使用了fetch,这个查询只会产生一条SQL语句,比原来需要N+1条SQL语句在性能上有了极大的提升
排除相同的记录DISTINCT
使用关联查询,我们很经常得到重复的对象,如下面语句:
selectofromOrderoinnerjoinfetcho.orderItemsorderbyo.orderid"
当有N个orderItem时就会产生N个Order,而有些Order对象往往是相同的,这时我们需要使用DISTINCT关键字来排除掉相同的对象。
selectDISTINCTofromOrderoinnerjoinfetcho.orderItemsorderbyo.orderid
比较Entity
在查询中使用参数查询时,参数类型除了String,原始数据类型(int,double等)和它们的对象类型(Integer,Double等),也可以是Entity的实例。
//查询某人的所有订单
selectofromOrderowhereo.ower=?
1orderbyo.orderid"
Personperson=newPerson();
person.setPersonid(newInteger
(1));
query.setParameter(1,person);
批量更新(BatchUpdate)
HPQL支持批量更新
//把所有订单的金额加10
updateOrderasoseto.amount=o.amount+10"
//update的记录数
intresult=query.executeUpdate();
批量删除(BatchRemove)
//把金额小于100的订单删除,先删除订单子项,再删除订单
deletefromOrderItemitemwhereitem.orderin(fromOrderasowhereo.amount<
100)"
query.executeUpdate();
deletefromOrderasowhereo.amount<
100"
//delete的记录数
使用操作符NOT
//查询除了指定人之外的所有订单
selectofromOrderowherenot(o.ower=?
1)orderbyo.orderid"
person.setPersonid(newInteger
(2));
使用操作符BETWEEN
selectofromOrderasowhereo.amountbetween300and1000
使用操作符IN
//查找年龄为26,21的Person
selectpfromPersonaspwherep.agein(26,21)
使用操作符LIKE
//查找以字符串"
li"
开头的Person
selectpfromPersonaspwherep.namelike'
li%'
使用操作符ISNULL
//查询含有购买者的所有Order
selectofromOrderasowhereo.oweris[not]null
使用操作符ISEMPTY
ISEMPTY是针对集合属性(Collection)的操作符。
可以和NOT一起使用。
注:
低版权的Mysql不支持ISEMPTY
//查询含有订单项的所有Order
selectofromOrderasowhereo.orderItemsis[not]empty
使用操作符EXISTS
[NOT]EXISTS需要和子查询配合使用。
低版权的Mysql不支持EXISTS
//如果存在订单号为1的订单,就获取所有OrderItem
selectoifromOrderItemasoiwhereexists(selectofromOr
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- jpql 查询