Java程序员从笨鸟到菜鸟之(五十九)细谈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. }  
public class Student {

  private String id;

  private String name;

  private String description;

  private Team team;

.************set、get方法省略

}


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. }  
public class Team {

   private String id;

   private String teamname;

   private Set students;

***********set、get方法省略

}


从实体上我们可以看出,学生和团队是一个多对一得数据关系,这个我们以前都看过,也写过,相信大家都有已经很熟悉了。所以在此具体的配置文件我们也不多写了,我们主要来看一下配置排序的地方,下面我们看一下配置的详细代码:

  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>  
<!-- 以名称降序返回student集合 -->

    <set name="students" table="studentOrder" cascade="all" order-by="name desc">

      <key column="team_id"></key>

      <one-to-many class="Collection.Order.Student"/>

    </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();  
Transaction t=session.beginTransaction();

       

        Team team=(Team)session.createQuery("from Team t where t.teamname='team1'").uniqueResult();

        Set result=team.getStudents();

        for (Iterator iterator = result.iterator(); iterator.hasNext();) {

            Student object = (Student) iterator.next();

            System.out.println(object.getName());

        }
        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>  
Hibernate: select team0_.id as id1_, team0_.teamname as teamname1_ from teamOrder team0_ where team0_.teamname='team1'
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
hello
default
bug

 

从上面输出的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. }   
public PersistentCollection wrap
(SessionImplementor session, Object collection) {  

  return new PersistentSortedSet
( session, (java.util.SortedSet) collection );  

} 


从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. }  
public class User {

       privateint id;

       privateString name;

       //联系方式

       privateContact contact;

********************set、get省略

}


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. }  
public class Contact {

       privateString address;

       privateString contactTel;

       privateString email;

       privateString zipCode;

********************set、get省略

}


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>   
<?xmlversion="1.0"?>

<!DOCTYPEhibernate-mapping PUBLIC

         "-//Hibernate/Hibernate MappingDTD 3.0//EN"

         "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">

<hibernate-mapping>

         <classname="com.bjsxt.hibernate.User" table="t_user">

                  <idname="id">

                           <generatorclass="native"/>

                  </id>

                  <propertyname="name"/>

                  <componentname="contact">

                           <propertyname="address"/>

                           <propertyname="contactTel"/>

                           <propertyname="email"/>

                           <propertyname="zipCode"/>

                  </component>

         </class>

</hibernate-mapping> 


       从配置上来看,其实这个地方很好理解,user把contact看做是组成的一部分,只是把他抽出一个单独的实体类了而已,这也正好体现了代码的复用性,其实他就是一对一关系的映射。

 

      如果想要生成两张表,hibernate也提供了相关的配置机制,其实只是换了换标签而已,把component标签换成composite-element,仅此而已,这样就能生成两张表了。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值