<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    BlogJava 首頁 新隨筆 聯(lián)系 聚合 管理
      37 Posts :: 64 Stories :: 21 Comments :: 0 Trackbacks

    4.3 使用HQL查詢

    Hibernate提供了異常強大的查詢體系,使用Hibernate有多種查詢方式。可以選擇使用Hibernate的HQL查詢,或者使用條件查詢,甚至可以使用原生的SQL查詢語句,此外還提供了一種數(shù)據(jù)過濾功能,這些都可用于篩選目標數(shù)據(jù)。

    下面分別介紹Hibernate的4種數(shù)據(jù)篩選方法:

    4.3.1 HQL查詢

    HQL是Hibernate Query Language的縮寫,HQL的語法很像SQL的語法,但HQL是一種面向?qū)ο蟮牟樵冋Z言。因此,SQL的操作對象是數(shù)據(jù)表和列等數(shù)據(jù)對象,而HQL的操作對象是類、實例、屬性等。

    HQL是完全面向?qū)ο蟮牟樵冋Z言,因此可以支持繼承和多態(tài)等特征。

    HQL查詢依賴于Query類,每個Query實例對應(yīng)一個查詢對象。使用HQL查詢可按如下步驟進行:

    (1)獲取Hibernate Session對象;

    (2)編寫HQL語句;

    (3)以HQL語句作為參數(shù),調(diào)用Session的createQuery方法創(chuàng)建查詢對象;

    (4)如果HQL語句包含參數(shù),調(diào)用Query的setXxx方法為參數(shù)賦值;

    (5)調(diào)用Query對象的list等方法遍歷查詢結(jié)果。

    看下面的查詢示例:

    public class HqlQuery

    {

        public static void main(String[] args)throws Exception

        {

            HqlQuery mgr = new HqlQuery();

            //調(diào)用查詢方法

            mgr.findPersons();

            //調(diào)用第二個查詢方法

            mgr.findPersonsByHappenDate();

            HibernateUtil.sessionFactory.close();

        }

        //第一個查詢方法

        private void findPersons()

        {

            //獲得Hibernate Session

            Session sess = HibernateUtil.currentSession();

            //開始事務(wù)

            Transaction tx = sess.beginTransaction();

            //以HQL語句創(chuàng)建Query對象.

            //執(zhí)行setString方法為HQL語句的參數(shù)賦值

            //Query調(diào)用list方法訪問查詢的全部實例

            List pl = sess.createQuery("from Person p where p.myEvents.title

            = :eventTitle")

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

                            .list();

            //遍歷查詢的全部結(jié)果

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

            {

                Person p = ( Person )pit.next();

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

            }

            //提交事務(wù)

            tx.commit();

            HibernateUtil.closeSession();

        }

        //第二個查詢方法

        private void findPersonsByHappenDate()throws Exception

        {

            //獲得Hibernate Session對象

            Session sess = HibernateUtil.currentSession();

            Transaction tx = sess.beginTransaction();

            //解析出Date對象

            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");

            Date start = sdf.parse("2005-01-01");

            System.out.println("系統(tǒng)開始通過日期查找人" + start);

            //通過Session的createQuery方法創(chuàng)建Query對象

            //設(shè)置參數(shù)

            //返回結(jié)果集

            List pl = sess.createQuery(

                "from Person p where p.myEvents.happenDate between :firstDate

                and :endDate")

                            .setDate("firstDate",start)

                            .setDate("endDate",new Date())

                            .list();

            //遍歷結(jié)果集

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

            {

                Person p = ( Person )pit.next();

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

            }

            tx.commit();

            HibernateUtil.closeSession();

        }

    }

    通過上面的示例程序,可看出查詢步驟基本相似。Query對象可以連續(xù)多次設(shè)置參數(shù),這得益于Hibernate Query的設(shè)計。

    通常,setXxx方法的返回值都是void,但Hibernate Query的setXxx方法返回值是Query本身。因此,程序通過Session創(chuàng)建Query后,直接多次調(diào)用setXxx方法為HQL語句的參數(shù)賦值,再直接調(diào)用list方法返回查詢到的全部結(jié)果即可。

    Query還包含兩個方法:

       ● setFirstResult(int firstResult),設(shè)置返回的結(jié)果集從第幾條記錄開始。

       ● setMaxResults(int maxResults),設(shè)置本次查詢返回的結(jié)果數(shù)。

    這兩個方法用于實現(xiàn)Hibernate分頁。

    下面簡單介紹HQL語句的語法。

    HQL語句本身是不區(qū)分大小寫的。也就是說,HQL語句的關(guān)鍵字和函數(shù)都是不區(qū)分大小寫的。但HQL語句中所使用的包名、類名、實例名和屬性名都區(qū)分大小寫。

    4.3.2 HQL查詢的from子句

    from子句是最簡單的HQL語句,也是最基本的HQL語句。from關(guān)鍵字后緊跟持久化類的類名。例如:

    from Person

    表明從Person持久化類中選出全部的實例。

    大部分時候,推薦為該Person的每個實例起別名。例如:

    from Person as p

    在上面的HQL語句中,Person持久化類中的實例的別名為p,既然 p是實例名,因此也應(yīng)該遵守Java的命名規(guī)則:第一個單詞的首字母小寫,后面每個單詞的首字母大寫。

    命名別名時,as關(guān)鍵字是可選的,但為了增加可讀性,建議保留。

    from后還可同時出現(xiàn)多個持久化類,此時將產(chǎn)生一個笛卡兒積或跨表的連接。

    4.3.3 HQL查詢的select子句

    select子句用于確定選擇出的屬性,當然select選擇的屬性必須是from后持久化類包含的屬性。例如:

    select p.name from Person as p

    select可以選擇任意屬性,不僅可以選擇持久化類的直接屬性,還可以選擇組件屬性包含的屬性,例如:

    select p.name.firstName from Person as p

    select也支持將選擇出的屬性存入一個List對象中,例如:

    select new list(p.name , p.address) from Person as p

    甚至可以將選擇出的屬性直接封裝成對象,例如:

    select new ClassTest(p.name , p.address) from Person as p

    前提是ClassTest支持p.name和p.address的構(gòu)造器,假如p.name的數(shù)據(jù)類型是           String,p.address的數(shù)據(jù)類型是String,則ClassTest必須有如下的構(gòu)造器:

    ClassTest(String s1, String s2)

    select還支持給選中的表達式命名別名,例如:

    select p.name as personName from Person as p

    這種用法與new map結(jié)合使用更普遍。如:

    select new map(p.name as personName) from Person as p

    在這種情形下,選擇出的是Map結(jié)構(gòu),以personName為key,實際選出的值作為value。

    4.3.4 HQL查詢的聚集函數(shù)

    HQL也支持在選出的屬性上,使用聚集函數(shù)。HQL支持的聚集函數(shù)與SQL完全相同,有如下5個:

       ● avg,計算屬性平均值。

       ● count,統(tǒng)計選擇對象的數(shù)量。

       ● max,統(tǒng)計屬性值的最大值

       ● min,統(tǒng)計屬性值的最小值。

       ● sum,計算屬性值的總和。

    例如:

    select count(*) from Person

    select max(p.age) from Person as p

    select子句還支持字符串連接符、算術(shù)運算符以及SQL函數(shù)。如:

    select p.name || "" || p.address from Person as p

    select子句也支持使用distinct和all關(guān)鍵字,此時的效果與SQL中的效果完全相同。

    4.3.5 多態(tài)查詢

    HQL語句被設(shè)計成能理解多態(tài)查詢,from后跟的持久化類名,不僅會查詢出該持久化類的全部實例,還會查詢出該類的子類的全部實例。

    如下面的查詢語句:

    from Person as p

    該查詢語句不僅會查詢出Person的全部實例,還會查詢出Person的子類,如Teacher的全部實例,前提是Person和Teacher完成了正確的繼承映射。

    HQL支持在from子句中指定任何Java類或接口,查詢會返回繼承了該類的持久化子類的實例或返回實現(xiàn)該接口的持久化類的實例。下面的查詢語句返回所有被持久化的對象:

    from java.lang.Object o

    如果Named接口有多個持久化類,下面的語句將返回這些持久化類的全部實例:

    from Named as n

    注意:后面的兩個查詢將需要多個SQL SELECT語句,因此無法使用order by子句對結(jié)果集進行排序,從而,不允許對這些查詢結(jié)果使用Query.scroll()方法。

    4.3.6 HQL查詢的where子句

    where子句用于篩選選中的結(jié)果,縮小選擇的范圍。如果沒有為持久化實例命名別名,可以直接使用屬性名引用屬性。

    如下面的HQL語句:

    from Person where name like 'tom%'

    上面HQL語句與下面的語句效果相同:

    from Person as p where p.name like "tom%"

    在后面的HQL語句中,如果為持久化實例命名了別名,則應(yīng)該使用完整的屬性名。兩個HQL語句都可返回name屬性以tom開頭的實例。

    復合屬性表達式加強了where子句的功能,例如如下HQL語句:

    from Cat cat where cat.mate.name like "kit%"

    該查詢將被翻譯成為一個含有內(nèi)連接的SQL查詢,翻譯后的SQL語句如下:

    select * from cat_table as table1 cat_table as table2 where table1.mate =

    table2.id and table1.name like "kit%"

    再看下面的HQL查詢語句:

    from Foo foo where foo.bar.baz.customer.address.city like"guangzhou%"

    翻譯成SQL查詢語句,將變成一個四表連接的查詢。

    =運算符不僅可以被用來比較屬性的值,也可以用來比較實例:

    from Cat cat, Cat rival where cat.mate = rival.mate

    select cat, mate

    from Cat cat, Cat mate

    where cat.mate = mate

    特殊屬性(小寫)id可以用來表示一個對象的標識符。(也可以使用該對象的屬性名。)

    from Cat as cat where cat.id = 123

    from Cat as cat where cat.mate.id = 69

    第二個查詢是一個內(nèi)連接查詢,但在HQL查詢語句下,無須體會多表連接,而完全使用面向?qū)ο蠓绞降牟樵儭?/p>

    id也可代表引用標識符。例如,Person類有一個引用標識符,它由country屬性 與medicareNumber兩個屬性組成。

    下面的HQL語句有效:

    from Person as person

    where person.id.country = 'AU'

        and person.id.medicareNumber = 123456

    from Account as account

    where account.owner.id.country = 'AU'

        and account.owner.id.medicareNumber = 123456

    第二個查詢跨越兩個表Person和Account。是一個多表連接查詢,但此處感受不到多表連接查詢的效果。

    在進行多態(tài)持久化的情況下,class關(guān)鍵字用來存取一個實例的鑒別值(discriminator value)。嵌入where子句中的Java類名,將被作為該類的鑒別值。例如:

    from Cat cat where cat.class = DomesticCat

    where子句中的屬性表達式必須以基本類型或java.lang.String結(jié)尾,不要使用組件類型屬性結(jié)尾,例如Account有Person屬性,而Person有Name屬性,Name有firstName屬性。

    看下面的情形:

    from Account as a where a.person.name.firstName like "dd%" //正確

    from Account as a where a.person.name like "dd%" //錯誤

    4.3.7 表達式

    HQL的功能非常豐富,where子句后支持的運算符異常豐富,不僅包括SQL的運算符,還包括EJB-QL的運算符等。

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

       ● 數(shù)學運算符+、–、*、/?等。

       ● 二進制比較運算符=、>=、<=、<>、!=、like等。

       ● 邏輯運算符and、or、not等。

       ● in、not in、between、is null、is not null、is empty、is not empty、member of和not member of等。

       ● 簡單的case、case ... when ... then ... else ... end和case、case when ... then ... else ...       end等。

       ● 字符串連接符value1 || value2或使用字符串連接函數(shù)concat(value1 , value2)。

       ● 時間操作函數(shù)current_date()、current_time()、current_timestamp()、second()、minute()、hour()、day()、month()、year()等。

       ● HQL還支持EJB-QL 3.0所支持的函數(shù)或操作substring()、trim()、lower()、upper()、length()、locate()、abs()、sqrt()、bit_length()、coalesce()和nullif()等。

       ● 還支持數(shù)據(jù)庫的類型轉(zhuǎn)換函數(shù),如cast(... as ...),第二個參數(shù)是Hibernate的類型名,或者extract(... from ...),前提是底層數(shù)據(jù)庫支持ANSI cast()?和extract()。

       ● 如果底層數(shù)據(jù)庫支持如下單行函數(shù)sign()、trunc()、rtrim()、sin()。則HQL語句也完全可以支持。

       ● HQL語句支持使用?作為參數(shù)占位符,這與JDBC的參數(shù)占位符一致,也可使用命名參數(shù)占位符號,方法是在參數(shù)名前加冒號 :,例如 :start_date和:x1等。

       ● 當然,也可在where子句中使用SQL常量,例如'foo'、69、'1970-01-01 10:00:         01.0'等。

       ● 還可以在HQL語句中使用Java public static final 類型的常量,例如eg.Color.TABBY。

    除此之外,where子句還支持如下的特殊關(guān)鍵字用法。

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

    from DomesticCat cat where cat.name between 'A' and 'B'

    from DomesticCat cat where cat.name in ( 'Foo','Bar','Baz')

       ● 當然,也支持not in和not between...and的使用,例如:

    from DomesticCat cat where cat.name not between 'A' and 'B'

    from DomesticCat cat where cat.name not in ( 'Foo','Bar','Baz' )

       ● 子句is null與is not null可以被用來測試空值,例如:

    from DomesticCat cat where cat.name is null;

    from Person as p where p.address is not null;

    如果在Hibernate配置文件中進行如下聲明:

    <property name="hibernate.query.substitutions">true 1, false 0</property>

    上面的聲明表明,HQL轉(zhuǎn)換SQL語句時,將使用字符1和0來取代關(guān)鍵字true和false。然后將可以在表達式中使用布爾表達式,例如:

    from Cat cat where cat.alive = true

       ● size關(guān)鍵字用于返回一個集合的大小,例如:

    from Cat cat where cat.kittens.size > 0

    from Cat cat where size(cat.kittens) > 0

       ● 對于有序集合,還可使用minindex與maxindex函數(shù)代表最小與最大的索引序數(shù)。同理,可以使用minelement與maxelement函數(shù)代表集合中最小與最大的元素。         例如:

    from Calendar cal where maxelement(cal.holidays) > current date

    from Order order where maxindex(order.items) > 100

    from Order order where minelement(order.items) > 10000

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

    //操作集合元素

    select mother from Cat as mother, Cat as kit

    where kit in elements(foo.kittens)

    //p的name屬性等于集合中某個元素的name屬性

    select p from NameList list, Person p

    where p.name = some elements(list.names)

    //操作集合元素

    from Cat cat where exists elements(cat.kittens)

    from Player p where 3 > all elements(p.scores)

    from Show show where 'fizard' in indices(show.acts)

    注意這些結(jié)構(gòu)變量size、elements、indices、minindex、maxindex、minelement、maxelement 等,只能在where子句中使用。

       ● where子句中,有序集合的元素(arrays, lists, maps)可以通過[ ]運算符訪問。例如:

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

    from Order order where order.items[0].id = 1234

    //holidays是map集合屬性,holidays[national day]代表其中一個元素

    select person from Person person, Calendar calendar

    where calendar.holidays['national day'] = person.birthDay

    and person.nationality.calendar = calendar

    //下面同時使用list 集合和map集合屬性

    select item from Item item, Order order

    where order.items[ order.deliveredItemIndices[0] ] = item and order.id = 11

    select item from Item item, Order order

    where order.items[ maxindex(order.items) ] = item and order.id = 11

    在[]中的表達式甚至可以是一個算術(shù)表達式,例如:

    select item from Item item, Order order

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

    借助于HQL,可以大大簡化選擇語句的書寫,提高查詢語句的可讀性,看下面的HQL語句:

    select cust

    from Product prod,

        Store store

        inner join store.customers cust

    where prod.name = 'widget'

        and store.location.name in ( 'Melbourne', 'Sydney' )

        and prod = all elements(cust.currentOrder.lineItems)

    如果翻譯成SQL語句,將變成如下形式:

    SELECT cust.name, cust.address, cust.phone, cust.id, cust.current_order

    FROM customers cust,

        stores store,

        locations loc,

        store_customers sc,

        product prod

    WHERE prod.name = 'widget'

        AND store.loc_id = loc.id

        AND loc.name IN ( 'Melbourne', 'Sydney' )

        AND sc.store_id = store.id

        AND sc.cust_id = cust.id

        AND prod.id = ALL(

            SELECT item.prod_id

            FROM line_items item, orders o

            WHERE item.order_id = o.id

                AND cust.current_order = o.id

        )

    4.3.8 order by子句

    查詢返回的列表(list)可以根據(jù)類或組件屬性的任何屬性進行排序,例如:

    from Person as p

    order by p.name, p.age

    還可使用asc或desc關(guān)鍵字指定升序或降序的排序規(guī)則,例如:

    from Person as p

    order by p.name asc , p.age desc

    如果沒有指定排序規(guī)則,默認采用升序規(guī)則。即是否使用asc關(guān)鍵字是沒有區(qū)別的,加asc是升序排序,不加asc也是升序排序。

    4.3.9 group by子句

    返回聚集值的查詢可以對持久化類或組件屬性的屬性進行分組,分組所使用的group by子句。看下面的HQL查詢語句:

    select cat.color, sum(cat.weight), count(cat)

    from Cat cat

    group by cat.color

    類似于SQL的規(guī)則,出現(xiàn)在select后的屬性,要么出現(xiàn)在聚集函數(shù)中,要么出現(xiàn)在group by的屬性列表中。看下面示例:

    //select后出現(xiàn)的id出現(xiàn)在group by之后,而name屬性則出現(xiàn)在聚集函數(shù)中

    select foo.id, avg(name), max(name)

    from Foo foo join foo.names name

    group by foo.id

    having子句用于對分組進行過濾,如下:

    select cat.color, sum(cat.weight), count(cat)

    from Cat cat

    group by cat.color

    having cat.color in (eg.Color.TABBY, eg.Color.BLACK)

    注意:having子句用于對分組進行過濾,因此having子句只能在有g(shù)roup by子句時才可以使用,沒有g(shù)roup by子句,不能使用having子句。

    Hibernate的HQL語句會直接翻譯成數(shù)據(jù)庫SQL語句。因此,如果底層數(shù)據(jù)庫支持的having子句和group by子句中出現(xiàn)一般函數(shù)或聚集函數(shù),HQL語句的having子句和order by 子句中也可以出現(xiàn)一般函數(shù)和聚集函數(shù)。

    例如:

    select cat

    from Cat cat

    join cat.kittens kitten

    group by cat

    having avg(kitten.weight) > 100

    order by count(kitten) asc, sum(kitten.weight) desc

    注意:group by子句與 order by子句中都不能包含算術(shù)表達式。

    4.3.10 子查詢

    如果底層數(shù)據(jù)庫支持子查詢,則可以在HQL語句中使用子查詢。與SQL中子查詢相似的是,HQL中的子查詢也需要使用()括起來。如:

    from Cat as fatcat

    where fatcat.weight > ( select avg(cat.weight) from DomesticCat cat )

    如果select中包含多個屬性,則應(yīng)該使用元組構(gòu)造符:

    from Cat as cat

    where not ( cat.name, cat.color ) in (

        select cat.name, cat.color from DomesticCat cat

    )

    4.3.11 fetch關(guān)鍵字

    對于集合屬性,Hibernate默認采用延遲加載策略。例如,對于持久化類Person,有集合屬性scores。加載Person實例時,默認不加載scores屬性。如果Session被關(guān)閉,Person實例將無法訪問關(guān)聯(lián)的scores屬性。

    為了解決該問題,可以在Hibernate映射文件中取消延遲加載或使用fetch join,例如:

    from Person as p join p.scores

    上面的fetch語句將會初始化person的scores集合屬性。

    如果使用了屬性級別的延遲獲取,可以使用fetch all properties來強制Hibernate立即抓取那些原本需要延遲加載的屬性,例如:

    from Document fetch all properties order by name

    from Document doc fetch all properties where lower(doc.name) like '%cats%'

    4.3.12 命名查詢

    HQL查詢還支持將查詢所用的HQL語句放入配置文件中,而不是代碼中。通過這種方式,可以大大提供程序的解耦。

    使用query元素定義命名查詢,下面是定義命名查詢的配置文件片段:

    <!-- 定義命名查詢 -->

    <query name="myNamedQuery">

        <!-- 此處確定命名查詢的HQL語句 -->

        from Person as p where p.age > ?

    </query>

    該命名的HQL查詢可以直接通過Session訪問,調(diào)用命名查詢的示例代碼如下:

    private void findByNamedQuery()throws Exception

    {

        //獲得Hibernate Session對象

        Session sess = HibernateUtil.currentSession();

        //開始事務(wù)

        Transaction tx = sess.beginTransaction();

        System.out.println("執(zhí)行命名查詢");

        //調(diào)用命名查詢

        List pl = sess.getNamedQuery("myNamedQuery")

                            //為參數(shù)賦值

                           .setInteger(0 , 20)

                            //返回全部結(jié)果

                           .list();

        //遍歷結(jié)果集

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

        {

            Person p = ( Person )pit.next();

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

        }

        //提交事務(wù)

        tx.commit();

        HibernateUtil.closeSession();

    }

    posted on 2009-09-22 10:47 xiachang88 閱讀(1076) 評論(0)  編輯  收藏

    只有注冊用戶登錄后才能發(fā)表評論。


    網(wǎng)站導航:
     
    主站蜘蛛池模板: ssswww日本免费网站片| 国产在线播放线91免费| 免费VA在线观看无码| 久久免费国产精品| 黄瓜视频高清在线看免费下载 | 久久这里只精品99re免费| 青春禁区视频在线观看直播免费 | 亚洲女女女同性video| 特黄特色的大片观看免费视频| 91禁漫免费进入| 亚洲成?v人片天堂网无码| 亚洲毛片在线观看| 免费精品国产自产拍在线观看 | 日本一区午夜艳熟免费| 黄a大片av永久免费| 亚洲精品午夜国产VA久久成人| 亚洲人成网站色在线观看| 在线播放免费人成毛片乱码| 亚洲精品乱码久久久久久中文字幕| 东北美女野外bbwbbw免费| 久久久久久a亚洲欧洲AV| 特级aa**毛片免费观看| 毛片a级三毛片免费播放| 亚洲AV乱码一区二区三区林ゆな| 99国产精品视频免费观看| 国产成人精品日本亚洲网站| 深夜特黄a级毛片免费播放| 久久亚洲国产精品123区| 精品国产_亚洲人成在线| 成年女人毛片免费观看97| 久久精品国产亚洲AV天海翼 | 一二三四免费观看在线电影| 亚洲AV午夜成人影院老师机影院| 另类小说亚洲色图| 国产大片51精品免费观看| 亚洲日本一线产区和二线产区对比| 国产精品免费视频网站| a视频免费在线观看| 亚洲av最新在线网址| 97无码免费人妻超级碰碰夜夜| 免费看又黄又爽又猛的视频软件|