Hibernate的HQL查询.docx

上传人:b****4 文档编号:4926378 上传时间:2022-12-11 格式:DOCX 页数:14 大小:22.81KB
下载 相关 举报
Hibernate的HQL查询.docx_第1页
第1页 / 共14页
Hibernate的HQL查询.docx_第2页
第2页 / 共14页
Hibernate的HQL查询.docx_第3页
第3页 / 共14页
Hibernate的HQL查询.docx_第4页
第4页 / 共14页
Hibernate的HQL查询.docx_第5页
第5页 / 共14页
点击查看更多>>
下载资源
资源描述

Hibernate的HQL查询.docx

《Hibernate的HQL查询.docx》由会员分享,可在线阅读,更多相关《Hibernate的HQL查询.docx(14页珍藏版)》请在冰豆网上搜索。

Hibernate的HQL查询.docx

Hibernate的HQL查询

4.3使用HQL查询

Hibernate提供了异常强大的查询体系,使用Hibernate有多种查询方式。

可以选择使用Hibernate的HQL查询,或者使用条件查询,甚至可以使用原生的SQL查询语句,此外还提供了一种数据过滤功能,这些都可用于筛选目标数据。

下面分别介绍Hibernate的4种数据筛选方法:

4.3.1HQL查询

HQL是HibernateQueryLanguage的缩写,HQL的语法很像SQL的语法,但HQL是一种面向对象的查询语言。

因此,SQL的操作对象是数据表和列等数据对象,而HQL的操作对象是类、实例、属性等。

HQL是完全面向对象的查询语言,因此可以支持继承和多态等特征。

HQL查询依赖于Query类,每个Query实例对应一个查询对象。

使用HQL查询可按如下步骤进行:

(1)获取HibernateSession对象;

(2)编写HQL语句;

(3)以HQL语句作为参数,调用Session的createQuery方法创建查询对象;

(4)如果HQL语句包含参数,调用Query的setXxx方法为参数赋值;

(5)调用Query对象的list等方法遍历查询结果。

看下面的查询示例:

publicclassHqlQuery

{

   publicstaticvoidmain(String[]args)throwsException

   {

       HqlQuerymgr=newHqlQuery();

       //调用查询方法

       mgr.findPersons();

       //调用第二个查询方法

       mgr.findPersonsByHappenDate();

       HibernateUtil.sessionFactory.close();

   }

   //第一个查询方法

   privatevoidfindPersons()

   {

       //获得HibernateSession

       Sessionsess=HibernateUtil.currentSession();

       //开始事务

       Transactiontx=sess.beginTransaction();

       //以HQL语句创建Query对象.

       //执行setString方法为HQL语句的参数赋值

       //Query调用list方法访问查询的全部实例

       Listpl=sess.createQuery("fromPersonpwherep.myEvents.title

       =:

eventTitle")

                       .setString("eventTitle","很普通事情")

                       .list();

       //遍历查询的全部结果

       for(Iteratorpit=pl.iterator();pit.hasNext();)

       {

           Personp=(Person)pit.next();

           System.out.println(p.getName());

       }

       //提交事务

      mit();

       HibernateUtil.closeSession();

   }

   //第二个查询方法

   privatevoidfindPersonsByHappenDate()throwsException

   {

       //获得HibernateSession对象

       Sessionsess=HibernateUtil.currentSession();

       Transactiontx=sess.beginTransaction();

       //解析出Date对象

       SimpleDateFormatsdf=newSimpleDateFormat("yyyy-MM-dd");

       Datestart=sdf.parse("2005-01-01");

       System.out.println("系统开始通过日期查找人"+start);

       //通过Session的createQuery方法创建Query对象

       //设置参数

       //返回结果集

       Listpl=sess.createQuery(

           "fromPersonpwherep.myEvents.happenDatebetween:

firstDate

           and:

endDate")

                       .setDate("firstDate",start)

                       .setDate("endDate",newDate())

                       .list();

       //遍历结果集

       for(Iteratorpit=pl.iterator();pit.hasNext();)

      {

          Personp=(Person)pit.next();

           System.out.println(p.getName());

      }

       mit();

       HibernateUtil.closeSession();

   }

}

通过上面的示例程序,可看出查询步骤基本相似。

Query对象可以连续多次设置参数,这得益于HibernateQuery的设计。

通常,setXxx方法的返回值都是void,但HibernateQuery的setXxx方法返回值是Query本身。

因此,程序通过Session创建Query后,直接多次调用setXxx方法为HQL语句的参数赋值,再直接调用list方法返回查询到的全部结果即可。

Query还包含两个方法:

  ●setFirstResult(intfirstResult),设置返回的结果集从第几条记录开始。

  ●setMaxResults(intmaxResults),设置本次查询返回的结果数。

这两个方法用于实现Hibernate分页。

下面简单介绍HQL语句的语法。

HQL语句本身是不区分大小写的。

也就是说,HQL语句的关键字和函数都是不区分大小写的。

但HQL语句中所使用的包名、类名、实例名和属性名都区分大小写。

4.3.2HQL查询的from子句

from子句是最简单的HQL语句,也是最基本的HQL语句。

from关键字后紧跟持久化类的类名。

例如:

fromPerson

表明从Person持久化类中选出全部的实例。

大部分时候,推荐为该Person的每个实例起别名。

例如:

fromPersonasp

在上面的HQL语句中,Person持久化类中的实例的别名为p,既然p是实例名,因此也应该遵守Java的命名规则:

第一个单词的首字母小写,后面每个单词的首字母大写。

命名别名时,as关键字是可选的,但为了增加可读性,建议保留。

from后还可同时出现多个持久化类,此时将产生一个笛卡儿积或跨表的连接。

4.3.3HQL查询的select子句

select子句用于确定选择出的属性,当然select选择的属性必须是from后持久化类包含的属性。

例如:

selectp.namefromPersonasp

select可以选择任意属性,不仅可以选择持久化类的直接属性,还可以选择组件属性包含的属性,例如:

selectp.name.firstNamefromPersonasp

select也支持将选择出的属性存入一个List对象中,例如:

selectnewlist(p.name,p.address)fromPersonasp

甚至可以将选择出的属性直接封装成对象,例如:

selectnewClassTest(p.name,p.address)fromPersonasp

前提是ClassTest支持p.name和p.address的构造器,假如p.name的数据类型是          String,p.address的数据类型是String,则ClassTest必须有如下的构造器:

ClassTest(Strings1,Strings2)

select还支持给选中的表达式命名别名,例如:

selectp.nameaspersonNamefromPersonasp

这种用法与newmap结合使用更普遍。

如:

selectnewmap(p.nameaspersonName)fromPersonasp

在这种情形下,选择出的是Map结构,以personName为key,实际选出的值作为value。

4.3.4HQL查询的聚集函数

HQL也支持在选出的属性上,使用聚集函数。

HQL支持的聚集函数与SQL完全相同,有如下5个:

  ●avg,计算属性平均值。

  ●count,统计选择对象的数量。

  ●max,统计属性值的最大值

  ●min,统计属性值的最小值。

  ●sum,计算属性值的总和。

例如:

selectcount(*)fromPerson

selectmax(p.age)fromPersonasp

select子句还支持字符串连接符、算术运算符以及SQL函数。

如:

selectp.name||""||p.addressfromPersonasp

select子句也支持使用distinct和all关键字,此时的效果与SQL中的效果完全相同。

4.3.5多态查询

HQL语句被设计成能理解多态查询,from后跟的持久化类名,不仅会查询出该持久化类的全部实例,还会查询出该类的子类的全部实例。

如下面的查询语句:

fromPersonasp

该查询语句不仅会查询出Person的全部实例,还会查询出Person的子类,如Teacher的全部实例,前提是Person和Teacher完成了正确的继承映射。

HQL支持在from子句中指定任何Java类或接口,查询会返回继承了该类的持久化子类的实例或返回实现该接口的持久化类的实例。

下面的查询语句返回所有被持久化的对象:

fromjava.lang.Objecto

如果Named接口有多个持久化类,下面的语句将返回这些持久化类的全部实例:

fromNamedasn

注意:

后面的两个查询将需要多个SQLSELECT语句,因此无法使用orderby子句对结果集进行排序,从而,不允许对这些查询结果使用Query.scroll()方法。

4.3.6HQL查询的where子句

where子句用于筛选选中的结果,缩小选择的范围。

如果没有为持久化实例命名别名,可以直接使用属性名引用属性。

如下面的HQL语句:

fromPersonwherenamelike'tom%'

上面HQL语句与下面的语句效果相同:

fromPersonaspwherep.namelike"tom%"

在后面的HQL语句中,如果为持久化实例命名了别名,则应该使用完整的属性名。

两个HQL语句都可返回name属性以tom开头的实例。

复合属性表达式加强了where子句的功能,例如如下HQL语句:

fromCatcatwherecat.mate.namelike"kit%"

该查询将被翻译成为一个含有内连接的SQL查询,翻译后的SQL语句如下:

select * fromcat_tableastable1cat_tableastable2wheretable1.mate=

table2.idandtable1.namelike"kit%"

再看下面的HQL查询语句:

fromFoofoowherefoo.bar.baz.customer.address.citylike"guangzhou%"

翻译成SQL查询语句,将变成一个四表连接的查询。

=运算符不仅可以被用来比较属性的值,也可以用来比较实例:

fromCatcat,Catrivalwherecat.mate=rival.mate

selectcat,mate

fromCatcat,Catmate

wherecat.mate=mate

特殊属性(小写)id可以用来表示一个对象的标识符。

(也可以使用该对象的属性名。

fromCatascatwherecat.id=123

fromCatascatwherecat.mate.id=69

第二个查询是一个内连接查询,但在HQL查询语句下,无须体会多表连接,而完全使用面向对象方式的查询。

id也可代表引用标识符。

例如,Person类有一个引用标识符,它由country属性与medicareNumber两个属性组成。

下面的HQL语句有效:

fromPersonasperson

whereperson.id.country='AU'

   andperson.id.medicareNumber=123456

fromAccountasaccount

whereaccount.owner.id.country='AU'

   andaccount.owner.id.medicareNumber=123456

第二个查询跨越两个表Person和Account。

是一个多表连接查询,但此处感受不到多表连接查询的效果。

在进行多态持久化的情况下,class关键字用来存取一个实例的鉴别值(discriminatorvalue)。

嵌入where子句中的Java类名,将被作为该类的鉴别值。

例如:

fromCatcatwherecat.class=DomesticCat

where子句中的属性表达式必须以基本类型或java.lang.String结尾,不要使用组件类型属性结尾,例如Account有Person属性,而Person有Name属性,Name有firstName属性。

看下面的情形:

fromAccountasawherea.person.name.firstNamelike"dd%"//正确

fromAccountasawherea.person.namelike"dd%"//错误

4.3.7表达式

HQL的功能非常丰富,where子句后支持的运算符异常丰富,不仅包括SQL的运算符,还包括EJB-QL的运算符等。

where子句中允许使用大部分SQL支持的表达式:

  ●数学运算符+、–、*、/ 等。

  ●二进制比较运算符=、>=、<=、<>、!

=、like等。

  ●逻辑运算符and、or、not等。

  ●in、notin、between、isnull、isnotnull、isempty、isnotempty、memberof和notmemberof等。

  ●简单的case、case...when...then...else...end和case、casewhen...then...else...      end等。

  ●字符串连接符value1||value2或使用字符串连接函数concat(value1,value2)。

  ●时间操作函数current_date()、current_time()、current_timestamp()、second()、minute()、hour()、day()、month()、year()等。

  ●HQL还支持EJB-QL3.0所支持的函数或操作substring()、trim()、lower()、upper()、length()、locate()、abs()、sqrt()、bit_length()、coalesce()和nullif()等。

  ●还支持数据库的类型转换函数,如cast(...as...),第二个参数是Hibernate的类型名,或者extract(...from...),前提是底层数据库支持ANSIcast() 和extract()。

  ●如果底层数据库支持如下单行函数sign()、trunc()、rtrim()、sin()。

则HQL语句也完全可以支持。

  ●HQL语句支持使用?

作为参数占位符,这与JDBC的参数占位符一致,也可使用命名参数占位符号,方法是在参数名前加冒号:

,例如:

start_date和:

x1等。

  ●当然,也可在where子句中使用SQL常量,例如'foo'、69、'1970-01-0110:

00:

        01.0'等。

  ●还可以在HQL语句中使用Javapublicstaticfinal类型的常量,例如eg.Color.TABBY。

除此之外,where子句还支持如下的特殊关键字用法。

  ●in与between...and可按如下方法使用:

fromDomesticCatcatwherecat.namebetween'A'and'B'

fromDomesticCatcatwherecat.namein('Foo','Bar','Baz')

  ●当然,也支持notin和notbetween...and的使用,例如:

fromDomesticCatcatwherecat.namenotbetween'A'and'B'

fromDomesticCatcatwherecat.namenotin('Foo','Bar','Baz')

  ●子句isnull与isnotnull可以被用来测试空值,例如:

fromDomesticCatcatwherecat.nameisnull;

fromPersonaspwherep.addressisnotnull;

如果在Hibernate配置文件中进行如下声明:

true1,false0

上面的声明表明,HQL转换SQL语句时,将使用字符1和0来取代关键字true和false。

然后将可以在表达式中使用布尔表达式,例如:

fromCatcatwherecat.alive=true

  ●size关键字用于返回一个集合的大小,例如:

fromCatcatwherecat.kittens.size>0

fromCatcatwheresize(cat.kittens)>0

  ●对于有序集合,还可使用minindex与maxindex函数代表最小与最大的索引序数。

同理,可以使用minelement与maxelement函数代表集合中最小与最大的元素。

        例如:

fromCalendarcalwheremaxelement(cal.holidays)>currentdate

fromOrderorderwheremaxindex(order.items)>100

fromOrderorderwhereminelement(order.items)>10000

  ●可以使用SQL函数any、some、all、exists、in操作集合里的元素,例如:

//操作集合元素

selectmotherfromCatasmother,Cataskit

wherekitinelements(foo.kittens)

//p的name属性等于集合中某个元素的name属性

selectpfromNameListlist,Personp

wherep.name=someelements(list.names)

//操作集合元素

fromCatcatwhereexistselements(cat.kittens)

fromPlayerpwhere3>allelements(p.scores)

fromShowshowwhere'fizard'inindices(show.acts)

注意这些结构变量size、elements、indices、minindex、maxindex、minelement、maxelement等,只能在where子句中使用。

  ●where子句中,有序集合的元素(arrays,lists,maps)可以通过[]运算符访问。

例如:

//items是有序集合属性,items[0]代表第一个元素

fromOrderorderwhereorder.items[0].id=1234

//holidays是map集合属性,holidays[nationalday]代表其中一个元素

selectpersonfromPersonperson,Calendarcalendar

wherecalendar.holidays['nationalday']=person.birthDay

andperson.nationality.calendar=calendar

//下面同时使用list集合和map集合属性

selectitemfromItemitem,Orderorder

whereorder.items[order.deliveredItemIndices[0]]=itemandorder.id=11

selectitemfromItemitem,Orderorder

whereorder.items[maxindex(order.items)]=itemandorder.id=11

在[]中的表达式甚至可以是一个算术表达式,例如:

selectitemfromItemitem,Orderorder

whereorder.items[size(order.items)-1]=item

借助于HQL,可以大大简化选择语句的书写,提高查询语句的可读性,看下面的HQL语句:

selectcust

f

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 求职职场 > 简历

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1