高級框架應(yīng)用開發(fā)案例教程九_第1頁
高級框架應(yīng)用開發(fā)案例教程九_第2頁
高級框架應(yīng)用開發(fā)案例教程九_第3頁
高級框架應(yīng)用開發(fā)案例教程九_第4頁
高級框架應(yīng)用開發(fā)案例教程九_第5頁
已閱讀5頁,還剩30頁未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進(jìn)行舉報或認(rèn)領(lǐng)

文檔簡介

Java高級框架應(yīng)用開發(fā)案例教程(九)

Hibernate查詢語言

主要內(nèi)容9.1HQL(HibernateQueryLanguage)9.2條件查詢(CriteriaQuery)9.3原生SQL查詢9.4項目案例9.1HQL(HibernateQueryLanguage)Hibernate最為強(qiáng)大的功能點之一:Hibernate查詢語言(HibernateQueryLanguage)。Hibernate支持三種查詢方式:HQL(HibernateQueryLanguage),條件查詢(CriteriaQuery)以及原生SQL查詢。其中最重要的是第一種,即HibernateQueryLanguage。9.1.HQL(HibernateQueryLanguage)Hibernate具有一種強(qiáng)大的查詢語言,它看上去很像SQL。但是實際上區(qū)別很大,HQL是完全面向?qū)ο蟮模邆淅^承、多態(tài)和關(guān)聯(lián)等特性。1.大小寫敏感性(CaseSensitivity)除了Java類和屬性名稱外,查詢都是大小寫不敏感的。所以,SeLeCT和sELEct以及SELECT相同的,但是net.sf.hibernate.eg.FOO和net.sf.hibernate.eg.Foo是不同的,foo.barSet和foo.BARSET也是不同的。9.1HQL(HibernateQueryLanguage)2.from子句最簡單的Hibernate查詢是這樣的形式:

fromeg.Cat它簡單的返回所有eg.Cat類的實例。

大部分情況下,你需要賦予它一個別名(alias),因為你在查詢的其他地方也會引用這個Cat。

fromeg.Catascat上面的語句為Cat賦予了一個別名cat。所以后面的查詢可以用這個簡單的別名了。as關(guān)鍵字是可以省略的,我們也可以寫成這樣:

fromeg.Catcat可以出現(xiàn)多個類,結(jié)果是它們的笛卡爾積,或者稱為“交叉”連接。

fromFormula,ParameterfromFormulaasform,Parameterasparam讓查詢中的別名服從首字母小寫的規(guī)則,這是一個好習(xí)慣。這和Java對局部變量的命名規(guī)范是一致的。(比如,domesticCat)9.1HQL(HibernateQueryLanguage)3.聯(lián)合(Associations)和連接(joins)你可以使用join定義兩個實體的連接,同時指明別名。

fromeg.Catascatinnerjoincat.mateasmateleftouterjoincat.kittensaskittenfromeg.Catascatleftjoincat.mate.kittensaskittensfromFormulaformfulljoinform.parameterparam支持的連接類型是從ANSISQL借用的:

內(nèi)連接,innerjoin

左外連接,leftouterjoin

右外連接,rightouterjoin

全連接,fulljoin(不常使用)9.1HQL(HibernateQueryLanguage)innerjoin,leftouterjoin和rightouterjoin都可以簡寫。fromeg.Catascatjoincat.mateasmateleftjoincat.kittensaskitten并且,加上"fetch"后綴的抓取連接可以讓聯(lián)合的對象隨著它們的父對象的初始化而初始化,只需要一個select語句。這在初始化一個集合的時候特別有用。它有效地覆蓋了映射文件中對關(guān)聯(lián)和集合的外連接定義。

fromeg.Catascatinnerjoinfetchcat.mateleftjoinfetchcat.kittens抓取連接一般不需要賦予別名,因為被聯(lián)合的對象應(yīng)該不會在where子句(或者任何其它子句)中出現(xiàn)。并且,被聯(lián)合的對象也不會在查詢結(jié)果中直接出現(xiàn)。它們是通過父對象進(jìn)行訪問的。9.1HQL(HibernateQueryLanguage)4.select子句select子句選擇在結(jié)果集中返回哪些對象和屬性。思考一下下面的例子:

selectmatefromeg.Catascatinnerjoincat.mateasmate這個查詢會選擇出作為其它貓(Cat)朋友(mate)的那些貓。當(dāng)然,你可以更加直接的寫成下面的形式:

selectcat.matefromeg.Catcat你甚至可以選擇集合元素,使用特殊的elements功能。下面的查詢返回所有貓的小貓。

selectelements(cat.kittens)fromeg.Catcat查詢可以返回任何值類型的屬性,包括組件類型的屬性:

selectfromeg.DomesticCatcatwherelike'fri%'

9.1HQL(HibernateQueryLanguage)select.firstNamefromCustomerascust查詢可以用元素類型是Object[]的一個數(shù)組返回多個對象和/或多個屬性。

selectmother,offspr,fromeg.DomesticCatasmotherinnerjoinmother.mateasmateleftouterjoinmother.kittensasoffspr或者實際上是類型安全的Java對象

selectnewFamily(mother,mate,offspr)fromeg.DomesticCatasmotherjoinmother.mateasmateleftjoinmother.kittensasoffspr上面的代碼假定Family有一個合適的構(gòu)造函數(shù)。9.1HQL(HibernateQueryLanguage)5.統(tǒng)計函數(shù)(Aggregatefunctions)HQL查詢可以返回屬性的統(tǒng)計函數(shù)的結(jié)果。

selectavg(cat.weight),sum(cat.weight),max(cat.weight),count(cat)fromeg.Catcat在select子句中,統(tǒng)計函數(shù)的變量也可以是集合。

selectcat,count(elements(cat.kittens))fromeg.Catcatgroupbycat下面是支持的統(tǒng)計函數(shù)列表:

avg(...),sum(...),min(...),max(...)

count(*)

count(...),count(distinct...),count(all...)distinct和all關(guān)鍵字的用法和語義與SQL相同。

selectdistinctfromeg.Catcatselectcount(distinct),count(cat)fromeg.Catcat9.1HQL(HibernateQueryLanguage)6.多態(tài)(polymorphism)查詢類似下面的查詢:

fromeg.Catascat返回的實例不僅僅是Cat,也有可能是子類的實例,比如DomesticCat。Hibernate查詢可以在from子句中使用任何Java類或者接口的名字。查詢可能返回所有繼承自這個類或者實現(xiàn)這個接口的持久化類的實例。下列查詢會返回所有的持久化對象:

fromjava.lang.Objecto可能有多個持久化類都實現(xiàn)了Named接口:

fromeg.Namedn,eg.Namedmwhere=請注意,上面兩個查詢都使用了超過一個SQL的SELECT。這意味著orderby子句將不會正確排序。9.1HQL(HibernateQueryLanguage)7.where子句where子句讓你縮小你要返回的實例的列表范圍。

fromeg.Catascatwhere='Fritz'返回所有名字為'Fritz'的Cat的實例。

selectfoofromeg.Foofoo,eg.Barbarwherefoo.startDate=bar.date會返回所有的滿足下列條件的Foo實例,它們存在一個對應(yīng)的bar實例,其date屬性與Foo的startDate屬性相等。復(fù)合路徑表達(dá)式令where子句變得極為有力。請看下面的例子:

fromeg.Catcatwhereisnotnull9.1HQL(HibernateQueryLanguage)這個查詢會被翻譯為帶有一個表間(inner)join的SQL查詢。如果你寫下類似這樣的語句:fromeg.Foofoowherefoo.bar.baz.customer.address.cityisnotnull你最終會得到的查詢,其對應(yīng)的SQL需要4個表間連接。

=操作符不僅僅用于判斷屬性是否相等,也可以用于實例:

fromeg.Catcat,eg.Catrivalwherecat.mate=rival.mateselectcat,matefromeg.Catcat,eg.Catmatewherecat.mate=mate特別的,小寫的id可以用來表示一個對象的惟一標(biāo)識。fromeg.Catascatwherecat.id=123fromeg.Catascatwherecat.mate.id=69第二個查詢是很高效的。不需要進(jìn)行表間連接!9.1HQL(HibernateQueryLanguage)組合的標(biāo)示符也可以使用。假設(shè)Person有一個組合標(biāo)示符,是由country和medicareNumber組合而成的。frombank.Personpersonwhereperson.id.country='AU'andperson.id.medicareNumber=123456frombank.Accountaccountwhereaccount.owner.id.country='AU'andaccount.owner.id.medicareNumber=123456這里我們再次看到,第二個查詢不需要表間連接。

類似的,在存在多態(tài)持久化的情況下,特殊屬性class用于獲取某個實例的辨識值。在where子句中嵌入的Java類名將會轉(zhuǎn)換為它的辨識值。

fromeg.Catcatwherecat.class=eg.DomesticCat9.1HQL(HibernateQueryLanguage)你也可以指定組件(或者是組件的組件,依次類推)或者組合類型中的屬性。但是在一個存在路徑的表達(dá)式中,最后不能以一個組件類型的屬性結(jié)尾。(這里不是指組件的屬性)。比如,假若store.owner這個實體的的address是一個組件

store.owner.address.city//ok!store.owner.address//no!“任意(any)”類型也有特殊的id屬性和class屬性,這可以讓我們用下面的形式來表達(dá)連接(這里AuditLog.item是一個對應(yīng)到<ant>的屬性)。

fromeg.AuditLoglog,eg.Paymentpaymentwherelog.item.class='eg.Payment'andlog.item.id=payment.id注意上面查詢中,log.item.class和payment.class會指向兩個值,代表完全不同的數(shù)據(jù)庫字段。9.1HQL(HibernateQueryLanguage)8.表達(dá)式(Expressions)where子句允許出現(xiàn)的表達(dá)式包括了你在SQL中可以使用的大多數(shù)情況:

數(shù)學(xué)操作+,-,*,/

真假比較操作=,>=,<=,<>,!=,like

邏輯操作and,or,not

字符串連接||

SQL標(biāo)量(scalar)函數(shù),例如upper()和lower()

沒有前綴的()表示分組

in,between,isnull

JDBC傳入?yún)?shù)?

命名參數(shù):name,:start_date,:x1

SQL文字'foo',69,'1970-01-0110:00:01.0'

Java的publicstaticfinal常量比如Color.TABBYin和between可以如下例一樣使用:fromeg.DomesticCatcatwherebetween'A'and'B'fromeg.DomesticCatcatwherein('Foo','Bar','Baz')其否定形式為

fromeg.DomesticCatcatwherenotbetween'A'and'B'fromeg.DomesticCatcatwherenotin('Foo','Bar','Baz')類似的,isnull和isnotnull可以用來測試null值。9.1HQL(HibernateQueryLanguage)通過在Hibernate配置中聲明HQL查詢的替換方式,Boolean也是很容易在表達(dá)式中使用的:<propertyname="hibernate.query.substitutions">true1,false0</property>在從HQL翻譯成SQL的時候,關(guān)鍵字true和false就會被替換成1和0。

fromeg.Catcatwherecat.alive=true你可以用特殊屬性size來測試一個集合的長度,或者用特殊的size()函數(shù)也可以。

fromeg.Catcatwherecat.kittens.size>0fromeg.Catcatwheresize(cat.kittens)>0對于排序集合,你可以用minIndex和maxIndex來獲取其最大索引值和最小索引值。類似的,minElement和maxElement可以用來獲取集合中最小和最大的元素,前提是必須是基本類型的集合。

fromCalendarcalwherecal.holidays.maxElement>currentdate也有函數(shù)的形式(和上面的形式不同,函數(shù)形式是大小寫不敏感的):

fromOrderorderwheremaxindex(order.items)>100fromOrderorderwhereminelement(order.items)>100009.1HQL(HibernateQueryLanguage)SQL中的any,some,all,exists,in功能也是支持的,前提是必須把集合的元素或者索引集作為它們的參數(shù)(使用element和indices函數(shù)),或者使用子查詢的結(jié)果作為參數(shù)。selectmotherfromeg.Catasmother,eg.Cataskitwherekitinelements(foo.kittens)selectpfromeg.NameListlist,eg.Personpwhere=someelements(s)fromeg.Catcatwhereexistselements(cat.kittens)fromeg.Playerpwhere3>allelements(p.scores)fromeg.Showshowwhere'fizard'inindices(show.acts)請注意這些概念:size,elements,indices,minIndex,maxIndex,minElement,maxElement都有一些使用限制:

在where子句中:只對支持子查詢的數(shù)據(jù)庫有效

在select子句中:只有elements和indices有效9.1HQL(HibernateQueryLanguage)有序的集合(數(shù)組、list、map)的元素可以用索引來進(jìn)行引用(只限于在where子句中)fromOrderorderwhereorder.items[0].id=1234selectpersonfromPersonperson,Calendarcalendarwherecalendar.holidays['nationalday']=person.birthDayandperson.nationality.calendar=calendarselectitemfromItemitem,Orderorderwhereorder.items[order.deliveredItemIndices[0]]=itemandorder.id=11selectitemfromItemitem,Orderorderwhereorder.items[maxindex(order.items)]=itemandorder.id=11[]中的表達(dá)式允許是另一個數(shù)學(xué)表達(dá)式。

selectitemfromItemitem,Orderorderwhereorder.items[size(order.items)-1]=item9.1HQL(HibernateQueryLanguage)HQL也對一對多關(guān)聯(lián)或者值集合提供內(nèi)置的index()函數(shù)。selectitem,index(item)fromOrderorderjoinorder.itemsitemwhereindex(item)<5底層數(shù)據(jù)庫支持的標(biāo)量SQL函數(shù)也可以使用

fromeg.DomesticCatcatwhereupper()like'FRI%'假如以上的這些還沒有讓你信服的話,請想象一下下面的查詢假若用SQL來寫,會變得多么長,多么難讀:

selectcustfromProductprod,Storestoreinnerjoinstore.customerscustwhere='widget'andin('Melbourne','Sydney')andprod=allelements(cust.currentOrder.lineItems)9.1HQL(HibernateQueryLanguage)對應(yīng)的SQL語句可能是這樣的

SELECT,cust.address,cust.phone,cust.id,cust.current_orderFROMcustomerscust,storesstore,locationsloc,store_customerssc,productprodWHERE='widget'ANDstore.loc_id=loc.idANDIN('Melbourne','Sydney')ANDsc.store_id=store.idANDsc.cust_id=cust.idANDprod.id=ALL(SELECTd_idFROMline_itemsitem,ordersoWHEREitem.order_id=o.idANDcust.current_order=o.id)9.1HQL(HibernateQueryLanguage)9.orderby子句查詢返回的列表可以按照任何返回的類或者組件的屬性排序:

fromeg.DomesticCatcatorderbyasc,cat.weightdesc,cat.birthdateasc和desc是可選的,分別代表升序或者降序。10.groupby子句返回統(tǒng)計值的查詢可以按照返回的類或者組件的任何屬性排序:

selectcat.color,sum(cat.weight),count(cat)fromeg.Catcatgroupbycat.colorselectfoo.id,avg(elements(s)),max(indices(s))fromeg.Foofoogroupbyfoo.id請注意:你可以在select子句中使用elements和indices指令,即使你的數(shù)據(jù)庫不支持子查詢也可以。

9.1HQL(HibernateQueryLanguage)having子句也是允許的。selectcat.color,sum(cat.weight),count(cat)fromeg.Catcatgroupbycat.colorhavingcat.colorin(eg.Color.TABBY,eg.Color.BLACK)在having子句中允許出現(xiàn)SQL函數(shù)和統(tǒng)計函數(shù),當(dāng)然這需要底層數(shù)據(jù)庫支持才行。selectcatfromeg.Catcatjoincat.kittenskittengroupbycathavingavg(kitten.weight)>100orderbycount(kitten)asc,sum(kitten.weight)desc注意,groupby子句和orderby子句都不支持?jǐn)?shù)學(xué)表達(dá)式。9.1HQL(HibernateQueryLanguage)11.子查詢對于支持子查詢的數(shù)據(jù)庫來說,Hibernate支持在查詢中嵌套子查詢。子查詢必須由圓括號包圍(常常是在一個SQL統(tǒng)計函數(shù)中)。也允許關(guān)聯(lián)子查詢(在外部查詢中作為一個別名出現(xiàn)的子查詢)。

fromeg.Catasfatcatwherefatcat.weight>(selectavg(cat.weight)fromeg.DomesticCatcat)fromeg.DomesticCatascatwhere=some(selectname.nickNamefromeg.Nameasname)fromeg.Catascatwherenotexists(fromeg.Catasmatewheremate.mate=cat)fromeg.DomesticCatascatwherenotin(selectname.nickNamefromeg.Nameasname)9.2條件查詢(CriteriaQuery)9.2.條件查詢(CriteriaQuery)現(xiàn)在Hibernate也支持一種直觀的、可擴(kuò)展的條件查詢API。目前為止,這個API還沒有更成熟的HQL查詢那么強(qiáng)大,也沒有那么多查詢能力。特別要指出,條件查詢也不支持投影(projection)或統(tǒng)計函數(shù)(aggregation)。

1.創(chuàng)建一個Criteria實例net.sf.hibernate.Criteria這個接口代表對一個特定的持久化類的查詢。Session是用來制造Criteria實例的工廠。

Criteriacrit=sess.createCriteria(Cat.class);crit.setMaxResults(50);Listcats=crit.list();2.縮小結(jié)果集范圍一個查詢條件(Criterion)是net.sf.hibernate.expression.Criterion接口的一個實例。類net.sf.hibernate.expression.Expression定義了獲得一些內(nèi)置的Criterion類型。

Listcats=sess.createCriteria(Cat.class).add(Expression.like("name","Fritz%")).add(Expression.between("weight",minWeight,maxWeight)).list();9.2條件查詢(CriteriaQuery)表達(dá)式(Expressions)可以按照邏輯分組.Listcats=sess.createCriteria(Cat.class).add(Expression.like("name","Fritz%")).add(Expression.or( Expression.eq("age",newInteger(0)), Expression.isNull("age"))).list();Listcats=sess.createCriteria(Cat.class).add(Expression.in("name",newString[]{"Fritz","Izi","Pk"})).add(Expression.disjunction().add(Expression.isNull("age")).add(Expression.eq("age",newInteger(0))).add(Expression.eq("age",newInteger(1))).add(Expression.eq("age",newInteger(2))))).list();有很多預(yù)制的條件類型(Expression的子類)。有一個特別有用,可以讓你直接嵌入SQL。

Listcats=sess.createCriteria(Cat.class).add(Expression.sql("lower($)likelower(?)","Fritz%",Hibernate.STRING)).list();其中的{alias}是一個占位符,它將會被所查詢實體的行別名所替代。9.2條件查詢(CriteriaQuery)3.對結(jié)果排序可以使用net.sf.hibernate.expression.Order對結(jié)果集排序.Listcats=sess.createCriteria(Cat.class).add(Expression.like("name","F%").addOrder(Order.asc("name")).addOrder(Order.desc("age")).setMaxResults(50).list();9.2條件查詢(CriteriaQuery)4.關(guān)聯(lián)(Associations)你可以在關(guān)聯(lián)之間使用createCriteria(),很容易地在存在關(guān)系的實體之間指定約束。

Listcats=sess.createCriteria(Cat.class).add(Expression.like("name","F%").createCriteria("kittens").add(Expression.like("name","F%").list();注意,第二個createCriteria()返回一個Criteria的新實例,指向kittens集合類的元素。9.2條件查詢(CriteriaQuery)下面的替代形式在特定情況下有用。Listcats=sess.createCriteria(Cat.class).createAlias("kittens","kt").createAlias("mate","mt").add(Expression.eqProperty("","")).list();(createAlias())并不會創(chuàng)建一個Criteria的新實例。)

請注意,前面兩個查詢中Cat實例所持有的kittens集合類并沒有通過criteria預(yù)先過濾!如果你希望只返回滿足條件的kittens,你必須使用returnMaps()。

Listcats=sess.createCriteria(Cat.class).createCriteria("kittens","kt").add(Expression.eq("name","F%")).returnMaps().list();Iteratoriter=cats.iterator();while(iter.hasNext()){Mapmap=(Map)iter.next();Catcat=(Cat)map.get(Criteria.ROOT_ALIAS);Catkitten=(Cat)map.get("kt");}9.2條件查詢(CriteriaQuery)5.動態(tài)關(guān)聯(lián)對象獲?。―ynamicassociationfetching)可以在運(yùn)行時通過setFetchMode()來改變關(guān)聯(lián)對象自動獲取的策略。

Listcats=sess.createCriteria(Cat.class).add(Expression.like("name","Fritz%"))

.setFetchMode("mate",FetchMode.EAGER).setFetchMode("kittens",FetchMode.EAGER).list();這個查詢會通過外連接(outerjoin)同時獲得mate和kittens。6.根據(jù)示例查詢(Examplequeries)net.sf.hibernate.expression.Example類允許你從指定的實例創(chuàng)造查詢條件。

Catcat=newCat();cat.setSex('F');cat.setColor(Color.BLACK);Listresults=session.createCriteria(Cat.class).add(Example.create(cat)).list();版本屬性,表示符屬性和關(guān)聯(lián)都會被忽略。默認(rèn)情況下,null值的屬性也被排除在外。9.2條件查詢(CriteriaQuery)YoucanadjusthowtheExampleisapplied.你可以調(diào)整示例(Example)如何應(yīng)用。Exampleexample=Example.create(cat).excludeZeroes()//excludezerovaluedproperties.excludeProperty("color")//excludethepropertynamed"color".ignoreCase()//performcaseinsensitivestringcomparisons.enableLike();//uselikeforstringcomparisonsListresults=session.createCriteria(Cat.class).add(example).list();你甚至可以用示例對關(guān)聯(lián)對象建立criteria。

Listresults=session.createCriteria(Cat.class).add(Example.create(cat)).createCriteria("mate").add(Example.create(cat.getMate())).list();9.3原生SQL查詢9.3.原生SQL查詢你也可以直接使用你的數(shù)據(jù)庫方言表達(dá)查詢。在你想使用數(shù)據(jù)庫的某些特性的時候,這是非常有用的,比如Oracle中的CONNECT關(guān)鍵字。這也會掃清你把原來直接使用SQL/JDBC的程序移植到Hibernate道路上的障礙。

1.創(chuàng)建一個基于SQL的Query和普通的HQL查詢一樣,SQL查詢同樣是從

溫馨提示

  • 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論