1. 程式人生 > >Hibernate查詢(HQL——Hibernate Query Language)

Hibernate查詢(HQL——Hibernate Query Language)

增加 exceptio 連接查詢 有一個 子句 內容 ike 例子 範圍

HQL查詢

  HQL提供了是十分強大的功能,它是針對持久化對象,用取得對象,而不進行update,delete和insert等操作。而且HQL是面向對象的,具備繼承,多態和關聯等特性。

from子句:

  from子句是最簡單的HQL,例如from Student,也可以寫成 select s from Student s。它簡單的返回Student類的所有實例。值得註意的是除了JAVA類和屬性的名稱外,HQL語句對大小寫不敏感。

select子句:

有時並不需要取得對象的所有屬性,這時可以使用select子句進行屬性查詢,如select s.name from Student s。

統計函數查詢

可以在HQL中使用函數,經常使用的函數如下:

count():統計記錄條數。

min():求最小值。

max():求最大值。

sum():求和。

avg():求平均值。

例,要取得Student實例的數量,可以編寫如下HQL語句:

  select count(*) from Student

取得Student平均年齡的HQL語句:

  select avg(s.age) from Student as s

可以使用distinct去除重復的數據:

  select distinct s.age from Student as s

where子句:

  HQL也支持子查詢,它通過where子句實現這一機制。where子句可以讓用戶縮小要返回的實例的列表範圍。例如下面語句會返回所有名字為"Bill"的Student實例:

  Query query = session.createQuery("from Student as s where s.name=‘Bill‘");

where子句允許出現的表達式包括了SQL中可以使用的大多數情況。

常用操作符

數學操作:+,-,*,/

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

邏輯操作:and ,or, not

字符串連接:||

SQL標題函數 :如upper()和lower()

如果查詢返回多條記錄,可以用以下關鍵字來量化

all:表示所有的記錄。

any:表示所有記錄中的任意一條。

some:與any相同。

in:與any等價。

exists:表示子查詢至少要返回一條記錄。

例如,下面語句返回所有學生年齡都大於18的班級對象

  from Group g where 18<all (select s.age from g.students s)

下列語句返回在所有學生中有一個學生的年齡等於22的班級:

  from Group g where 22 = any (select s.age from g.students s)

或者

  from Group g where 22= some(select s.age from g.students s)

或者

  from Group g where 22 in (select s.age from g.students s)

連接查詢

與SQL一樣,HQL也支持連接查詢,如內連接,外連接和交叉連接:

inner join:內連接

left outer join:左外連接

rigth outer join:右外連接

full join:全連接,但不常用

order by子句

查詢返回列表可以按照任何返回的類或者組件的屬性排序

  from Student s order by s.name asc

Criteria Query方式

  當查詢數據時,往往需要設置查詢條件。在SQL或HQL語句中,查詢條件常常放在where子句中。此處Hibernate還支持Criteria查詢,這種查詢方式把查詢條件封裝為一個Criteria對象。在實際應用中,可以使用Session的createCriteria()方法構建一個org.hibernate.Criteria實例,然後把具體的查詢條件通過Criteria的add方法加入到Criteria實例中。這樣程序員可以在不使用SQL甚至HQL的情況下進行數據查詢。

常用的查詢限制方法

代碼中 Restrictions.eq()方法表示equal,即等於的情況。Restrictions類提供了查詢限制機制。它提供了許多方法,以實現查詢限制

Restrictions.eq():equal,=

Restrictions.allEq(): 參數為Map對象,使用key/value進行多個等於的對比,相當於多個Restrictions.eq()的效果

Restrictions.gt():greater-than: >

Restrictions.lt():less-than:<

Restrictions.le:less-equal:<=

Restrictions.between():對應SQL的between子句。

Restrictions.like():對應SQL的like子句。

Restrictions.in():對應SQL的in子句。

Restrictions.and():and 關系。

Restrictions.or():or 關系。

Restrictions.isNull():判斷屬性是否為空,為空返回true,否則返回false。

Restrictions.isNoyNull():與上面的相反。

Order.asc():根據傳入的字段進行升序排序。

Order.desc():與上相反

MatchMode.EXACT:字符串中精確匹配,相當於like ‘value‘

MatchMode.ANYWHERE:字符串在中間位置,相當於like‘%value%‘

MatchMode.START:字符串在最前面,相當於like‘value%‘

MatchMode.END:字符串在最後,相當於like‘%value‘

下面是幾個查詢限制的例子:

查詢學生名字以t開關的所有Student對象

Criteria criertia = session.createCriteria(Student.class);

criteria.add(Restrictions.like("name", "t%"));

List list
= criteria.list(); Student stu = (Student)list.get(0);

或者:

  Criteria criertia = session.createCriteria(Student.class);

  criteria.add(Restrictions.like("name", "t",MatchMode.START));

  List list = criteria.list();

  Student stu = (Student)list.get(0);

查詢學生姓名在Bill,Jack和Tom之間所有的Student對象

 String[] names = {"Bill","Jack","Tom"};

  Criteria criertia = session.createCriteria(Student.class);

  criteria.add(Restrictions.in("name", names));

  List list = criteria.list();

  Student stu = (Student)list.get(0);

查詢學生年齡(age)等於22或為空(null)的所有學生對象

Criteria criertia = session.createCriteria(Student.class);

  criteria.add(Restrictions.eq("age", new Integer(22)));

  criteria.add(Restrictions.isNull("age"));

  List list = criteria.list();

  Student stu = (Student)list.get(0);

查詢學生姓名以字母F開頭的所有Student對象,並按姓名升序排序

Criteria criertia = session.createCriteria(Student.class);

  criteria.add(Restrictions.like("name", "F%"));

  criteria.addOrder(Order.asc("name"));

  List list = criteria.list();

  Student stu = (Student)list.get(0);

註意調用Order.asc的方法應該是Criteria.addOrder()方法。

連接限制

Criteria查詢中使用FetchMode來實現連接限制。在HQL語句中,可以通過fetch關鍵字來表示預先抓取(Eager fetching),如下:

from Group g

left join fetch g.students s

where g.name like ‘%2005‘

可以使用Criteria的API完成同樣的功能

Native SQL查詢

  本地SQL查詢指的是直接使用本地數據庫的SQL語言進行查詢。這樣做對於將原來的SQL/JDBC程序遷移到Hibernate應用很有用。創建一個基於SQL的Query Native SQL查詢是通過SQLQuery接口來控制的,它通過調用Session.createSQLQuery()方法來獲得。

命名SQL查詢

與HQL的命名查詢相似,也可以將 本地的SQK查詢語句定義在映射文件中,然後像調用一個命名HQL查詢一樣專題報道調用命名SQL查詢。

Hibernate中Session接口

1、Session的save()和persist()方法

Session的save()方法使一個臨時對象轉變為持久化對象。它完成以下操作:

  (1)將臨時對象加入到Session緩存中,使其進入持久化狀態。

  (2)選用映射文件指定的標識符生成器,為持久化對象分配唯一的OID。

  (3)計劃執行一個insert語句。

Session的save()方法是用來持久化臨時對象的。不應將持久化對象或遊離對象傳遞給save()方法。若將持久化對象傳遞給save()方法,則該步保存操作是多余的。若將遊離對象傳遞給save()方法,則會重新生成OID,再保存一次。

Session的persist()方法與save()方法類似,也能將臨時對象轉變為持久化對象。

persist()方法與save()方法的區別在於:persist()方法不保證立即為持久化對象的OID賦值,而是有可能在Session清理緩存的時候才為OID賦值。此外,如果是在事物邊界以外調用persist()方法,則該方法不會計劃執行insert語句。而save()方法不論是在事物邊界以外還是以內,都會計劃執行insert語句。

2、Session的load()與get()方法

Session的load()與get()方法都能從根據給定的OID從數據庫中加載一個持久化對象,這兩個方法的區別在於:

(1)當數據庫中不存在與OID對應的記錄時,load()方法拋出org.hibernate.ObjectNotFoundException異常,而get()方法返回為null。

(2)load方法采用配置的加載策略(默認為延遲加載),而get()方法則會忽略配置,總是采用立即加載方法。

3、Session的update()方法

Session的update()方法使一個遊離對象轉變為持久化對象。它完成以下操作:

(1)將遊離對象加入到Session緩存中,使其轉變為持久化對象。

(2)計劃執行一個update語句。

當update()方法關聯一個遊離對象時,若在Session的緩存中已存在相同的OID的對象時,會拋出異常。

4、Session的saveOrUpdate()方法

  Session的saveOrUpdate()方法同時包含了save()方法與update()方法的功能,如果傳入的參數是臨時對象,就調用save()方法;如果傳入的參數是遊離對象,就調用update()方法。HIbernate根據對象的OID,version版本屬性等來判斷參數是臨時對象還是遊離對象。

5、Session的merge()方法

Session的merge()方法能夠將一個遊離對象的屬性復制到一個持久化對象中。其處理流程如下:

  (1)根據遊離對象的OID到Session緩存中查找匹配的持久化對象。若找到匹配的持久化對象,則將遊離對象的屬性復制到持久化對象中,計劃實行一條update語句,然後返回持久化對象的引用。

  (2)如果在Session的緩存中沒有找到與遊離對象OID一致的持久化對象,那麽就試圖根據該OID從數據庫中加載持久化對象。如果數據庫中存在匹配的持久化對象,則將遊離對象的屬性復制到剛加載的持久化對象中,計劃實行一條update語句,然後返回持久化對象的引用。

  (3)如果數據庫中也不存在or對象是臨時對象時,則會新建一個對象,將屬性賦值到該新建對象中,再持久化新建對象,最後返回新建對象的引用。

merger()和saveOrUpdate()的區別:調用完meger()對象仍然是脫管狀態。

6、Session的delete()方法

Session的delete()方法用於從數據庫中刪除一個java對象。delete()方法既可以刪除持久化對象,也可以刪除遊離對象。其處理過程如下:

(1)如果傳入的參數是遊離對象,則先使遊離對象與Session關聯,使它變為持久化對象。如果參數是持久化對象,則忽略該步。

(2)計劃執行一個delete語句。

(3)把對象從Session緩存中刪除,該對象進入刪除狀態。

7、Session的replicate()方法

Session的replicate()方法能夠將一個數據庫中的對象復制到另一個數據庫中。

Hibernate檢索策略

  簡介: Hibernate的Session在加載一個Java對象時,可以將與這個對象相關聯的其他Java對象都加載到緩存中,以便程序及時調用。但有些情況下,我們不需要加載太多無用的對象到緩存中,一來這樣會撐爆內存,二來增加了訪問數據庫的次數。所以為了合理的使用緩存,Hibernate提供了幾種檢索策略來供用戶選擇。

種類:立即檢索策略、延遲檢索策略、左外連接檢索策略

1、立即檢索策略

采用立即檢索策略,會將被檢索的對象,以及和這個對象關聯的一對多對象都加載到緩存中。Session的get方法就使用的立即檢索策略。

優點:頻繁使用的關聯對象能夠被加載到緩存中。

缺點:1、占用內存。2、Select語句過多。

2、延遲檢索策略

  采用延遲檢索策略,就不會加載關聯對象的內容。直到第一次調用關聯對象時,才去加載關聯對象。在不涉及關聯類操作時,延遲檢索策略只適用於Session的load方法。涉及關聯類操作時,延遲檢索策略也能夠適用於get,list等操作。在類級別操作時, 延遲檢索策略,只加載類的OID不加載類的其他屬性,只用當第一次訪問其他屬性時,才回訪問數據庫去加載內容。(這裏使用了CGLIB生成了類的代理類)在關聯級別操作時,延遲檢索策略,只加載類本身,不加載關聯類,直到第一次調用關聯對象時,才去加載關聯對象程序模式都是用延遲加載策略。如果需要指定使用延遲加載策略。在配置文件中設置<class>的lazy=true,<set>的lazy=true或extra(增強延遲)<many-to-one>的lazy=proxy和no-proxy。

優點:由程序決定加載哪些類和內容,避免了大量無用的sql語句和內存消耗。

缺點:在Session關閉後,就不能訪問關聯類對象了。 需要確保在Session.close方法前,調用關聯對象。

3、左外連接檢索策略

采用左外連接檢索,能夠使用Sql的外連接查詢,將需要加載的關聯對象加載在緩存中。

<set>fetch設置為join,<many-to-one>的fetch設置為 join

優點:對應用程序完全透明,不管對象處於持久化狀態,還是遊離狀態,應用程序都可以方便的從一個對象導航到與它關聯的對象。2.使用了外連接,select語句數目少。

缺點:可能會加載應用程序不需要訪問的對象,白白浪費許多內存空間。2.復雜的數據庫表連接也會影響檢索性能。

batch-size屬性:

無論是立即檢索還是延遲檢索,都可以指定關聯查詢的數量,這就需要使用batch-size屬性來指定,指定關聯查詢數量,以減少批量檢索的數據數目。

Hibernate查詢(HQL——Hibernate Query Language)