SSH:Hibernate框架(Hibernate查詢排序和組件映射)



         在實際開發過程中,有很多用戶需要時要把查詢出來的結果進行排序顯示,而不是在數據庫裏面那樣順序混亂那樣的顯示,這樣的話我們不得不要對數據進行排序了,hibernate對數據排序提供了很好的支持,hibernate提供了兩種對查詢到得數據結果進行排序:1:數據庫排序,也就是說在數據庫內部就進行完了排序。2.內存排序,也就是說在數據庫中把數據加載到內存中在進行排序。其實一般我們推薦使用第二種排序方式,因爲在數據庫中排序的性能要遠遠高於在內存中排序的性能。

 

一:數據庫排序

        數據庫排序主要是使用集合標籤中的order-by屬性,格式主要是爲: order-by="字段名 排序方式”例如:order-by="name asc”name是指數據庫字段 asc是升序,在hibernate中,<set>、<idbag>、<map>、<list>元素都有order-by屬性,如果設置了該屬性,Hibernate會利用 order by 子句進行排序,使用order-by屬性,我們可以通過hbm文件執行生成的SQL如何使用orderby 查詢子句以返回排序後的結果集。下面我們就以一個具體的實例來具體看一下數據庫排序的內容

我們就以學生和團隊的關係來說一下:首先來看一下實體之間的數據結構關係:

Student.java

  1. public class Student {  
  2.   
  3.   private String id;  
  4.   
  5.   private String name;  
  6.   
  7.   private String description;  
  8.   
  9.   private Team team;  
  10.   
  11. .************set、get方法省略  
  12.   
  13. }  


Team.java

  1. public class Team {  
  2.   
  3.    private String id;  
  4.   
  5.    private String teamname;  
  6.   
  7.    private Set students;  
  8.   
  9. ***********set、get方法省略  
  10.   
  11. }  


從實體上我們可以看出,學生和團隊是一個多對一得數據關係,這個我們以前都看過,也寫過,相信大家都有已經很熟悉了。所以在此具體的配置文件我們也不多寫了,我們主要來看一下配置排序的地方,下面我們看一下配置的詳細代碼:

  1. <!-- 以名稱降序返回student集合 -->  
  2.   
  3.     <set name="students" table="studentOrder" cascade="all" order-by="name desc">  
  4.   
  5.       <key column="team_id"></key>  
  6.   
  7.       <one-to-many class="Collection.Order.Student"/>  
  8.   
  9.     </set>  


從上面可以看出,其實配置數據庫排序很簡單,僅僅是在集合標籤上配置一個order-by屬性即可。

下面我們就具體來看一下測試代碼:

  1. Transaction t=session.beginTransaction();  
  2.   
  3.          
  4.   
  5.         Team team=(Team)session.createQuery("from Team t where t.teamname='team1'").uniqueResult();  
  6.   
  7.         Set result=team.getStudents();  
  8.   
  9.         for (Iterator iterator = result.iterator(); iterator.hasNext();) {  
  10.   
  11.             Student object = (Student) iterator.next();  
  12.   
  13.             System.out.println(object.getName());  
  14.   
  15.         }  
  16.         t.commit();  


運行這塊代碼,我們一起來看一下控制檯的打印結果:
測試結果:

  1. Hibernate: select team0_.id as id1_, team0_.teamname as teamname1_ from teamOrder team0_ where team0_.teamname='team1'  
  2. Hibernate: select students0_.team_id as team4_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.name as name0_0_, students0_.description as descript3_0_0_, students0_.team_id as team4_0_0_ from studentOrder students0_ where students0_.team_id=? order by students0_.name desc  
  3. hello  
  4. default  
  5. bug<span style="font-size:18px;color:red;"></span>  

 

從上面輸出的sql語句就可以看出,我們查詢到得數據時以student表中的name進行排序的。所以我們數據庫排序的配置就這麼結束了。

 

二.內存排序

 

        內存排序,顧名思義,就是在內存中排序,把查詢到得結果加載到內存以後驚醒排序。Hibernate在配置文件中也給我提供了內存排序的配置,那就是sort屬性,它有兩個屬性值可以直接使用,分別是unsorted(不排序)以及natural(自然排序,即升序),此外,我們還可以自定義排序規則,方式是定義一個類,讓其實現Comparator接口,並且實現該接口中的compare方法,在該方法中實現排序規則即可。然後將該自定義排序規則的類名作爲sort的屬性值即可。<set>和<map>元素都具有sort屬性,如果設置了該屬性,就會對內存中的集合對象進行排序。


<set>元素的sort屬性爲natural,表示對集合中的字符串進行自然排序。Hibernate採用org.hibernate.PersistentSortedSet作爲Set的實現類,PersistentSortedSet類實現了 java.util.SortedSet接口。當Session保存一個對象時,會調用 org.hibernate.type.SortedSetType類的wrap()方法,把對象的集合屬性包裝爲 SortedSet類的實例,下面我們看一下wrap()方法的源代碼如下:

  1. public PersistentCollection wrap  
  2. (SessionImplementor session, Object collection) {    
  3.   
  4.   return new PersistentSortedSet  
  5. ( session, (java.util.SortedSet) collection );    
  6.   
  7. }   


從wrap()方法的源代碼看出,應用程序中創建的對象的集合屬性必須是java.util.SortedSet類型,否則以上wrap()方法會拋出ClassCastException。

其實內存排序和數據庫排序是一樣的,只是配置的參數不同而已,都是在集合標籤配置一下,所以在此我們就不以示例演示了。

 

三、組件映射(component)

  

       在hibernate中,component是某個實體對象的邏輯組成部分,它與實體的根本區別是,component是沒有標識的,它是一個邏輯組成部分,完全從屬於某個實體,這樣就在傳統數據庫上,實現了對象的細粒度劃分,層次分明,實現了面向對象的領域劃分

見下圖:

                      

UserEmployee中共同的屬性(各種聯繫方式)拿出來,放在(抽象到)到一個單獨的類中。這樣物理上看有三個類,不過實體類還是隻有UserEmployee兩個,也就是說數據庫裏只有UserEmployee兩張表。

下面我們就來看一下usercontact的實體及相關配置:

user.java

  1. public class User {  
  2.   
  3.        privateint id;  
  4.   
  5.        privateString name;  
  6.   
  7.        //聯繫方式  
  8.   
  9.        privateContact contact;  
  10.   
  11. ********************set、get省略  
  12.   
  13. }  


contact.java

  

  1. public class Contact {  
  2.   
  3.        privateString address;  
  4.   
  5.        privateString contactTel;  
  6.   
  7.        privateString email;  
  8.   
  9.        privateString zipCode;  
  10.   
  11. ********************set、get省略  
  12.   
  13. }  


user.hbm.xml


  1. <?xmlversionxmlversion="1.0"?>  
  2.   
  3. <!DOCTYPEhibernate-mapping PUBLIC  
  4.   
  5.          "-//Hibernate/Hibernate MappingDTD 3.0//EN"  
  6.   
  7.          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  8.   
  9. <hibernate-mapping>  
  10.   
  11.          <classnameclassname="com.bjsxt.hibernate.User" table="t_user">  
  12.   
  13.                   <idnameidname="id">  
  14.   
  15.                            <generatorclassgeneratorclass="native"/>  
  16.   
  17.                   </id>  
  18.   
  19.                   <propertynamepropertyname="name"/>  
  20.   
  21.                   <componentnamecomponentname="contact">  
  22.   
  23.                            <propertynamepropertyname="address"/>  
  24.   
  25.                            <propertynamepropertyname="contactTel"/>  
  26.   
  27.                            <propertynamepropertyname="email"/>  
  28.   
  29.                            <propertynamepropertyname="zipCode"/>  
  30.   
  31.                   </component>  
  32.   
  33.          </class>  
  34.   
  35. </hibernate-mapping>   


       從配置上來看,其實這個地方很好理解,user把contact看做是組成的一部分,只是把他抽出一個單獨的實體類了而已,這也正好體現了代碼的複用性,其實他就是一對一關係的映射。

 

      如果想要生成兩張表,hibernate也提供了相關的配置機制,其實只是換了換標籤而已,把component標籤換成composite-element,僅此而已,這樣就能生成兩張表了。

         在實際開發過程中,有很多用戶需要時要把查詢出來的結果進行排序顯示,而不是在數據庫裏面那樣順序混亂那樣的顯示,這樣的話我們不得不要對數據進行排序了,hibernate對數據排序提供了很好的支持,hibernate提供了兩種對查詢到得數據結果進行排序:1:數據庫排序,也就是說在數據庫內部就進行完了排序。2.內存排序,也就是說在數據庫中把數據加載到內存中在進行排序。其實一般我們推薦使用第二種排序方式,因爲在數據庫中排序的性能要遠遠高於在內存中排序的性能。

 

一:數據庫排序

        數據庫排序主要是使用集合標籤中的order-by屬性,格式主要是爲: order-by="字段名 排序方式”例如:order-by="name asc”name是指數據庫字段 asc是升序,在hibernate中,<set>、<idbag>、<map>、<list>元素都有order-by屬性,如果設置了該屬性,Hibernate會利用 order by 子句進行排序,使用order-by屬性,我們可以通過hbm文件執行生成的SQL如何使用orderby 查詢子句以返回排序後的結果集。下面我們就以一個具體的實例來具體看一下數據庫排序的內容

我們就以學生和團隊的關係來說一下:首先來看一下實體之間的數據結構關係:

Student.java

  1. public class Student {  
  2.   
  3.   private String id;  
  4.   
  5.   private String name;  
  6.   
  7.   private String description;  
  8.   
  9.   private Team team;  
  10.   
  11. .************set、get方法省略  
  12.   
  13. }  


Team.java

  1. public class Team {  
  2.   
  3.    private String id;  
  4.   
  5.    private String teamname;  
  6.   
  7.    private Set students;  
  8.   
  9. ***********set、get方法省略  
  10.   
  11. }  


從實體上我們可以看出,學生和團隊是一個多對一得數據關係,這個我們以前都看過,也寫過,相信大家都有已經很熟悉了。所以在此具體的配置文件我們也不多寫了,我們主要來看一下配置排序的地方,下面我們看一下配置的詳細代碼:

  1. <!-- 以名稱降序返回student集合 -->  
  2.   
  3.     <set name="students" table="studentOrder" cascade="all" order-by="name desc">  
  4.   
  5.       <key column="team_id"></key>  
  6.   
  7.       <one-to-many class="Collection.Order.Student"/>  
  8.   
  9.     </set>  


從上面可以看出,其實配置數據庫排序很簡單,僅僅是在集合標籤上配置一個order-by屬性即可。

下面我們就具體來看一下測試代碼:

  1. Transaction t=session.beginTransaction();  
  2.   
  3.          
  4.   
  5.         Team team=(Team)session.createQuery("from Team t where t.teamname='team1'").uniqueResult();  
  6.   
  7.         Set result=team.getStudents();  
  8.   
  9.         for (Iterator iterator = result.iterator(); iterator.hasNext();) {  
  10.   
  11.             Student object = (Student) iterator.next();  
  12.   
  13.             System.out.println(object.getName());  
  14.   
  15.         }  
  16.         t.commit();  


運行這塊代碼,我們一起來看一下控制檯的打印結果:
測試結果:

  1. Hibernate: select team0_.id as id1_, team0_.teamname as teamname1_ from teamOrder team0_ where team0_.teamname='team1'  
  2. Hibernate: select students0_.team_id as team4_1_, students0_.id as id1_, students0_.id as id0_0_, students0_.name as name0_0_, students0_.description as descript3_0_0_, students0_.team_id as team4_0_0_ from studentOrder students0_ where students0_.team_id=? order by students0_.name desc  
  3. hello  
  4. default  
  5. bug<span style="font-size:18px;color:red;"></span>  

 

從上面輸出的sql語句就可以看出,我們查詢到得數據時以student表中的name進行排序的。所以我們數據庫排序的配置就這麼結束了。

 

二.內存排序

 

        內存排序,顧名思義,就是在內存中排序,把查詢到得結果加載到內存以後驚醒排序。Hibernate在配置文件中也給我提供了內存排序的配置,那就是sort屬性,它有兩個屬性值可以直接使用,分別是unsorted(不排序)以及natural(自然排序,即升序),此外,我們還可以自定義排序規則,方式是定義一個類,讓其實現Comparator接口,並且實現該接口中的compare方法,在該方法中實現排序規則即可。然後將該自定義排序規則的類名作爲sort的屬性值即可。<set>和<map>元素都具有sort屬性,如果設置了該屬性,就會對內存中的集合對象進行排序。


<set>元素的sort屬性爲natural,表示對集合中的字符串進行自然排序。Hibernate採用org.hibernate.PersistentSortedSet作爲Set的實現類,PersistentSortedSet類實現了 java.util.SortedSet接口。當Session保存一個對象時,會調用 org.hibernate.type.SortedSetType類的wrap()方法,把對象的集合屬性包裝爲 SortedSet類的實例,下面我們看一下wrap()方法的源代碼如下:

  1. public PersistentCollection wrap  
  2. (SessionImplementor session, Object collection) {    
  3.   
  4.   return new PersistentSortedSet  
  5. ( session, (java.util.SortedSet) collection );    
  6.   
  7. }   


從wrap()方法的源代碼看出,應用程序中創建的對象的集合屬性必須是java.util.SortedSet類型,否則以上wrap()方法會拋出ClassCastException。

其實內存排序和數據庫排序是一樣的,只是配置的參數不同而已,都是在集合標籤配置一下,所以在此我們就不以示例演示了。

 

三、組件映射(component)

  

       在hibernate中,component是某個實體對象的邏輯組成部分,它與實體的根本區別是,component是沒有標識的,它是一個邏輯組成部分,完全從屬於某個實體,這樣就在傳統數據庫上,實現了對象的細粒度劃分,層次分明,實現了面向對象的領域劃分

見下圖:

                      

UserEmployee中共同的屬性(各種聯繫方式)拿出來,放在(抽象到)到一個單獨的類中。這樣物理上看有三個類,不過實體類還是隻有UserEmployee兩個,也就是說數據庫裏只有UserEmployee兩張表。

下面我們就來看一下usercontact的實體及相關配置:

user.java

  1. public class User {  
  2.   
  3.        privateint id;  
  4.   
  5.        privateString name;  
  6.   
  7.        //聯繫方式  
  8.   
  9.        privateContact contact;  
  10.   
  11. ********************set、get省略  
  12.   
  13. }  


contact.java

  

  1. public class Contact {  
  2.   
  3.        privateString address;  
  4.   
  5.        privateString contactTel;  
  6.   
  7.        privateString email;  
  8.   
  9.        privateString zipCode;  
  10.   
  11. ********************set、get省略  
  12.   
  13. }  


user.hbm.xml


  1. <?xmlversionxmlversion="1.0"?>  
  2.   
  3. <!DOCTYPEhibernate-mapping PUBLIC  
  4.   
  5.          "-//Hibernate/Hibernate MappingDTD 3.0//EN"  
  6.   
  7.          "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">  
  8.   
  9. <hibernate-mapping>  
  10.   
  11.          <classnameclassname="com.bjsxt.hibernate.User" table="t_user">  
  12.   
  13.                   <idnameidname="id">  
  14.   
  15.                            <generatorclassgeneratorclass="native"/>  
  16.   
  17.                   </id>  
  18.   
  19.                   <propertynamepropertyname="name"/>  
  20.   
  21.                   <componentnamecomponentname="contact">  
  22.   
  23.                            <propertynamepropertyname="address"/>  
  24.   
  25.                            <propertynamepropertyname="contactTel"/>  
  26.   
  27.                            <propertynamepropertyname="email"/>  
  28.   
  29.                            <propertynamepropertyname="zipCode"/>  
  30.   
  31.                   </component>  
  32.   
  33.          </class>  
  34.   
  35. </hibernate-mapping>   


       從配置上來看,其實這個地方很好理解,user把contact看做是組成的一部分,只是把他抽出一個單獨的實體類了而已,這也正好體現了代碼的複用性,其實他就是一對一關係的映射。

 

      如果想要生成兩張表,hibernate也提供了相關的配置機制,其實只是換了換標籤而已,把component標籤換成composite-element,僅此而已,這樣就能生成兩張表了。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章