Hibernate<7> Hibernate的檢索方式

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,而對於投影查詢,第二級緩存會存放全部的數據值。

後面咱們會詳細介紹緩存。

相關文章
相關標籤/搜索