Hibernate查詢(HQL——Hibernate Query Language)

HQL查詢

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

from子句:

  from子句是最簡單的HQL,例如from Student,也能夠寫成 select s from Student s。它簡單的返回Student類的全部實例。值得注意的是除了JAVA類和屬性的名稱外,HQL語句對大小寫不敏感。程序員

select子句:

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

統計函數查詢

能夠在HQL中使用函數,常用的函數以下:數據庫

count():統計記錄條數。緩存

min():求最小值。session

max():求最大值。less

sum():求和。函數

avg():求平均值。性能

例,要取得Student實例的數量,能夠編寫以下HQL語句:fetch

  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接口

一、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語句。

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

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

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

(2)load方法採用配置的加載策略(默認爲延遲加載),而get()方法則會忽略配置,老是採用當即加載方法。

三、Session的update()方法

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

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

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

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

四、Session的saveOrUpdate()方法

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

五、Session的merge()方法

Session的merge()方法可以將一個遊離對象的屬性複製到一個持久化對象中。其處理流程以下:

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

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

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

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

六、Session的delete()方法

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

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

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

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

七、Session的replicate()方法

Session的replicate()方法可以將一個數據庫中的對象複製到另外一個數據庫中。

Hibernate檢索策略

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

種類:當即檢索策略、延遲檢索策略、左外鏈接檢索策略

一、當即檢索策略

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

優勢:頻繁使用的關聯對象可以被加載到緩存中。

缺點:一、佔用內存。二、Select語句過多。

二、延遲檢索策略

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

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

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

三、左外鏈接檢索策略

採用左外鏈接檢索,可以使用Sql的外鏈接查詢,將須要加載的關聯對象加載在緩存中。

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

優勢:對應用程序徹底透明,無論對象處於持久化狀態,仍是遊離狀態,應用程序均可以方便的從一個對象導航到與它關聯的對象。2.使用了外鏈接,select語句數目少。

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

batch-size屬性:

不管是當即檢索仍是延遲檢索,均可以指定關聯查詢的數量,這就須要使用batch-size屬性來指定,指定關聯查詢數量,以減小批量檢索的數據數目。

相關文章
相關標籤/搜索