HIbernate提供瞭如下幾種檢索對象的方式:java
①、導航對象圖檢索方式:根據已經加載的對象,導航到其餘對象。例如,對於已經加載的Customer對象,調用它的getOrders().iterator()方法就能夠導航到所關聯的Order對象。數據庫
②、OID檢索方式:按照對象的OID來檢索對象,session的get()和load()方法提供了這種功能。若是在應用程序中事先知道了OID,就可使用這種檢索對象的方式。編程
③、HQL檢索方式:使用面向對象HQL查詢語言,Hibernate提供的Query接口,它是Hibernate提供的專門的HQL查詢接口,可以執行各類複雜的HQL查詢語句。緩存
④、QBC檢索方式:使用QBC(Query By Criteria)API來檢索對象,安全
⑤、本地SQL檢索方式。性能優化
⑥、QBE檢索方式:QBC的子功能。session
1、Hibernate檢索方式簡介:app
當直接使用JDBC API查詢數據庫時,必須在應用程序中嵌入冗長的SQL語句。性能
一、HQL檢索方式(Hibernate Query Language) HQL是面向對象查詢語言。fetch
二、QBC檢索方式(Query By Criteria) QBC API提供了檢索對象的另外一種方式,它主要是有Criteria接口、Criterion接口和Expression類組成,它支持在運行時動態生成查詢語句。
三、QBE檢索方式(Query By Example) 它是QBC的子功能。QBE容許先建立一個對象樣板,而後檢索出全部和這個樣板相同的對象。
四、Sql檢索方式:Sql檢索方與HQL檢索方式都使用Query接口,區別在於SQL檢索方式經過Session的createSQLQuery()方法來建立Query對象。
2、HQL檢索方式
一、使用別名:
經過HQL檢索一個類的實例時,若是查詢語句的其餘地方須要引用它,應該爲這個類指定一個別名,例如:from Customer as customer where customer.name=:name。as關鍵字用於設定別名,也能夠將as關鍵字省略。
二、多條查詢:
HQL和QBC都支持多態查詢,多態查詢指查詢出當前類及全部子類的實例。
三、對查詢結果排序
HQL與QBC都支持對查詢結果排序,HQL採用order by關鍵字對查詢結果排序,而QBC採用Order類對查詢結果排序。
//hql檢索方式
Query query=session.createQuery("from Customer customer order by customer.name");
//QBC方式
Criteria criteria=session.createCriteria(Customer.class);
criteria.addOrder(Order.asc("name"));
四、分頁查詢:
Query和Criteria接口都提供了用於分頁顯示查詢結果的方法:
setFirstResult(int firstResult):設定從哪個對象開始檢索。
setMaxResult(int maxResult):設定一次最多檢索出的對象數目。
五、檢索單個對象
Query和Criteria接口都提供瞭如下用以執行查詢語句並返回查詢結果的方法
list()方法:返回一個list類型的查詢結果,在List集合中存放了全部知足查詢條件的持久化對象。
uniqueResult()方法:返回單個對象
六、在HQL查詢語句中綁定參數
session=HibernateUtil.getSession(); Query query=session.createQuery("from Customer as customer where customer.name='"+name+"'"); List customers=query.list(); return customers;
上面的代碼儘管能夠,可是不安全,Hibernate採用參數綁定機制來避免以上問題,Hibernate的參數綁定機制依賴於JDBC API中PreparedStatement的預約義Sql語句功能。參數綁定有如下優勢:
①、很是安全。
②、可以利用底層數據庫預編譯SQL語句的功能,提供查詢數據的性能。預編譯是指在底層數據庫系統只須要編譯SQL語句一次,把編譯出來的可執行代碼保存在緩存中,若是屢次執行相同形式的SQL語句,不須要從新編譯,只要從緩存中得到可執行代碼便可。
參數綁定的形式有兩種:
<1>、按參數名字綁定
在HQL查詢語句中定義命名參數,命名參數以「:」開頭,形式以下:
Query query=session.createQuery("from Customer customer where customer.name=:name and customer.age=:age");
以上的HQL語句中定義了兩個參數:name,age。下面接下里調用Query的setXXX()方法綁定參數。
query.setString("name",name);
<2>、按參數位置綁定
在HQL中使用「?」來定義參數的位置,則HQL爲
Query query=session.createQuery("from Customer customer where customer.name=? and customer.age=?");
query.setString(0,name);
query.setInteger(1,age);
七、在映射文件中定義命名查詢語句
Hibernate容許再映射文件中定義字符串形式的查詢語句。在程序中經過Session的getNamedQuery()方法獲取該查詢語句。
八、設定查詢條件
HQL查詢語句也經過where字句來設定查詢條件,值得注意是,在where字句中給出的是對象的屬性名,而不是字段名。對於QBC查詢,必須建立一個Criterion對象來設定查詢條件。
HQL和QBC支持的各類運算
HQl運算符 | QBC運算符 | 含義 |
= | Expression.eq() | 等於 |
<> | Expression.not(Expression.eq()) | 不等於 |
> | Expression.gt() | 大於 |
>= | Expression.ge() | 大於等於 |
< | Expression.lt() | 小於 |
<= | Expression.le() | 小於等於 |
is null | Expression.isNull() | 等於空值 |
is not null | Expression.isNotNull() | 非空值 |
in | Expression.in() | 等於列表中的某一值 |
not in | Expression.not(Expression.in()) | |
between 值1 and 值2 | Expression.between() | |
not between 值1 and 值2 | Expression.not(Expression.between()) | |
like | Expression.like() | |
and | Expression.and()或者Expression.conjunction() | |
or | Expressioin.or() |
|
not | Expression.not() |
九、鏈接查詢
HQL與QBC也支持各類各樣的連接查詢,如內鏈接、外鏈接和交叉鏈接,迫切內鏈接、迫切外鏈接。
查詢類型 | HQL語法 | QBC語法 |
內鏈接 | inner join或 join | Criteria.createAlias() |
迫切內鏈接 | inner join fetch 或join fetch | 不支持 |
隱式內鏈接 | 不支持 | |
左外鏈接 | left outer join或者left join | 不支持 |
迫切左外鏈接 | left outer join fetch 或者 left join fetch | FetchMode.EAGER |
右外鏈接 | right outer join | 不支持 |
交叉鏈接 | ClassA,ClassB | 不支持 |
3、高級查詢-------動態查詢
一、HQL與QBC可以完成許多相同的任務,相比之下,HQL能更加直觀的表達複雜的查詢語句,而經過QBC表達複雜的查詢語句很麻煩。所以若是,在程序運行前就明確了查詢語句的內容(也成爲靜態查詢),應該優先考慮HQL查詢方式。可是若是隻有在程序運行時才能明確查詢 語句的內容(也稱爲動態查詢),QBC比HQL更加方便。
在實際應用中,常常有這樣的查詢需求:用戶在客戶界面的查詢窗口輸入查詢條件,按下查詢按鈕後,業務層執行查詢操做,返回匹配的查詢結果。
經過HQL來生成動態查詢語句:
public List findCustomers(String username,String password){ session=HibernateUtil.getSession(); StringBuffer hqlStr=new StringBuffer("from SysUser as user"); if(username!=null) hqlStr.append(" where user.username like :username"); if(password!=null && username!=null) hqlStr.append(" and user.password=:password"); if(password!=null && username==null) hqlStr.append(" where customer.password=:password"); Query query=session.createQuery(hqlStr.toString()); if(username!=null) query.setString("username", username); if(password!=null) query.setString("password", password); List list=query.list(); System.out.println(list.size()); return list; }
若是採用QBC檢索方式,能夠簡化編程:
public List findCustomers2(String username,String password){ session=HibernateUtil.getSession(); Criteria cri=session.createCriteria(SysUser.class); if(username!=null) cri.add(Expression.like("username", username,MatchMode.ANYWHERE)); if(password !=null) cri.add(Expression.eq("password", password)); List list=cri.list(); System.out.println(list.size()); return list; }
也可使用QBE檢索方式:
public List findCustomers3(Customer customer){ session=HibernateUtil.getSession(); Example exampleCustomer=Example.create(customer); exampleCustomer.ignoreCase().enableLike(MatchMode.ANYWHERE); exampleCustomer.excludeZeroes(); Criteria cri=session.createCriteria(SysUser.class).add(exampleCustomer); return cri.list(); }
二、集合過濾
Session的createFilter()方法用來過濾集合。
4、本地SQL查詢
HIbernate對本地SQL查詢提供了內置的支持,爲了把SQL查詢返回的關係數據映射爲對象,須要在SQL查詢語句中爲字段指定別名,Session的createSQLQuery()方法。
5、查詢性能優化
Hibernate主要從如下幾個方面來優化查詢性能:
一、下降訪問數據庫的頻率,減小select語句的數目。實現手段:
①、使用迫切左外鏈接或迫切內鏈接檢索策略。
②、對延遲檢索或當即檢索設置批量檢索數目。
③、使用查詢緩存。
二、避免多餘加載程序不須要訪問的數據,實現手段:
①、使用延遲檢索策略。
②、使用集合過濾。
三、避免報表查詢數據佔用緩存。實現手段爲利用投影查詢,查詢出實體的部分屬性。
四、減小select語句中的字段,從而下降訪問數據庫的數據量。實現手段:利用Query的iterate()方法。
6、iterate()方法
Query接口的iterate()方法和list()方法都能執行SQL查詢語句,可是前者在有些狀況下能輕微 提升查詢性能。例如,如下程序代碼兩次檢索Customer對象。
Query query1=session.CreateQuery("from Customer c");
List result1=query1.list();
Query query2=session.CreateQuery("from Customer c where c.age<30");
List result2=query2.list();
當第二次從數據庫檢索Customer對象時,Hibernate執行的SQL查詢語句爲select id,name ,age from customers where age <30
因爲和以上查詢結果對應的Customer對象已經存在於Session的緩存中,所以在這種狀況下,Hibernate不須要從新建立Customer對象,只須要根據查詢結果中的ID字段值返回緩存中匹配的Customer對象。可見,當第二次從數據庫中檢索Customer對象時,在select語句中其實只須要包含customer表的ID字段就能夠了。
Query接口的iterate()方法首先檢索ID字段,而後根據ID字段到Hibernate的第一級緩存以及第二級緩存中查找匹配的Customer對象,若是存在,就直接把它加入到查詢結果集中,不然就執行額外的select語句,根據ID字段到數據庫中檢索該對象。
7、查詢緩存
對於常用的查詢語句,若是啓用了查詢緩存,當第一次執行查詢語句時,Hibernate會把查詢結果存放在第二級緩存中。之後再次執行該查詢語句時,只需從緩存中得到查詢結果,從而提供查詢性能。若是查詢結果中包含實體,第二級緩存只會存放實體的OID,而對於投影查詢,第二級緩存會存放全部的數據值。
後面咱們會詳細介紹緩存。