在HIBERNATE中进行了一对多的映射,从一查出多,想把多的放在列表中,产生的数据是想同的,遍历后显示在界面上,相同的数据顺序就不一样了,很影响数据查看,如下面效果:
排序前:
排序后(问题解决):
修改HIBERNATE的配置文件(红色部分,project_t为project表的字段):
<set name="projects" cascade="all" lazy="false" order-by="project_t desc">
<key>
<column name="user_t" />
</key>
<one-to-many class="com.haier.db.entity.User_project_t" />
</set>
Collection结果集排序解析
无序集和有序集,是针对Hibernate数据持久过程中,是否保持数据集合中的记录排列顺序加以区分的。
也就是说,对于一个有序集,其中元素的排列次序将会在库表中制定的字段中保存,而下次读取时,也会以同样的次序排列。下面所要探讨的,则是关于Collection中的元素排序问题。
排序强调的是针对现有数据,以特定的逻辑对其排列次序进行调整。而排序的结果,是数据在内存中的某种排列次序,属于临时状态。
数据排序由两种方式:
1. Sort
Collection中的数据排序。如对一个List中的元素先后顺序进行调整。
2. order-by
对数据库执行Select SQL时,由order by子句实现的数据排序方式。
可以看出,这两种排序方式的最基本差异在于,Sort操作是在JVM中完成,而order-by是由数据库完成。
1. Sort
首先来看一个示例:
<set name=”addresses” lazy=”true” table=”t_address” sort=”naural”>
<key column=”user_id”/>
<element type=”string” column=”address”/>
</set>
可排序Set在Hibernate中对应的实现类为net.sf.hibernate.collection.SortedSet,它实现了java.util.SortedSet接口。
sort=”natural”指定采用Java默认排序机制,它会调用相应数据类型的compareTo方法进行排序中的值比对。这里<element type=”string”…>指定了元素类型为string,也就是说,排序将基于String.compareTo方法。
如果期望指定某种特殊的排序算法,那么我们可以实现java.util.Comparator接口,并以此实现作为排序的根据。如下面这段代码:
/**
*基于字符串长度的比对
*/
public class LengthComparator implements Comparator{
public int compare(Object obj1, Object obj2){
String str1 = String.valueOf(obj1);
String str2 = String.valueOf(obj2);
return str1.length()-str2.length();
}
}
作为示例,LengthComparator实现了字符串长度的比对,我们可以在配置中指定LengthComparator作为排序算法:
<set name=”addresses” lazy=”true” table=”t_address” sort=”org.sample.LengthComparator”>
<key column=”user_id”/>
<element type=”string” column=”address”/>
</set>
Map类型的排序与Set基本一致:
<map name="addresses" lazy="true" table="t_address" sort="org.sample.LengthComparator">
<key column="user_id"/>
<element type="string" column="address"/>
</map>
index呢,可排序Map在Hibernate中对应的实现类为net.sf.hibernate.collection.SortedMap,它实现了java.util.SortedMap接口。net.sf.hibernate.collection.SortedMap和.SortedSet的内部实现分别基于java.util.TreeSet和java.util.TreeMap。而Bag和List由于实现原理的不同(且JDK中也并不存在所谓的TreeList),并不支持sort排序方式。
2. order-by
Collection的order-by排序方式,其实现原理也是借助SQL的order by子句。
同样来看一个示例:
<set name="addresses" lazy="true" table="t_address" order-by="address desc">
<key column="user_id"/>
<element type="string" column="address"/>
</set>
在order-by属性中,我们指定了SQL排序子句。Hibernate在自动生成SQL时,会根据此项配置,自动在SQL中追加相应的order by子句。
运行以下代码:
TUser user = (TUser)session.load(TUser.class, new Integer(1));
Iterator it = user.getAddresses().iterator();
while(it.hasNext()){
String addr = (String)it.next();
System.out.println(addr);
}
观察Hibernate生成的SQL语句:
可以看到,Hibernate在生成SQL的时候,已经追加了order-by子句“order by addresses0_.address asc”.
注意:
order-by特性在实现中借助了JDK1.4中的新增集合类LinkedHashSet以及LinkedHashMap,因此order-by特性只支持在1.4版本以上的JDK中运行。
Set、Map、Bag均支持order-by排序,有序集List例外。