Sorting Hibernate Set using a comparator
Collection mappings in Hibernate can be configured to sort using a specific comparator.
Consider the following mapping
<hibernate-mapping> <class name="com.example.Person" table="PERSON"> ...... <set name="bankAccounts" lazy="true" cascade="all,delete-orphan" inverse="true" sort="natural"> <key> <column name="BANK_ACCOUNT_ID" precision="29" scale="0" not-null="true" /> </key> <one-to-many class="com.example.BankAccount" /> </set> ...... </class> </hibernate-mapping>
In the example above Hibernate will order the bankAccounts set according to their natural order. If the BankAccout class implements Comparable interface, compareTo method will be used to sort the Set.
What if you want to sort the set differently? What if you want to use a comparator to sort the set.
The sort attribute can have three possible values
The first option is
<set name="bankAccounts" lazy="true" cascade="all,delete-orphan" inverse="true" sort="natural">
which sorts by natural order
the second option is
<set name="bankAccounts" lazy="true" cascade="all,delete-orphan" inverse="true" sort="unsorted">
which tells Hibernate that the Set needs not to be sorted
and the third option is
<set name="bankAccounts" lazy="true" cascade="all,delete-orphan" inverse="true" sort="comparatorClass">
where you specify what comparator should be used to sort the Set.
Let’s see it through code example. For example suppose class BankAccount is defined as below
package com.example;
//import statements
public class BankAccount implements Comparable<BankAccount>, Serializable{
private String accountName;
private String accountShortName;
//getter and setter methods
public int compareTo(BankAccount that) {
final int BEFORE = -1;
final int AFTER = 1;
if (that == null) {
return BEFORE;
}
Comparable thisAccountName = this.getAccountName();
Comparable thatAccountName = that.getAccountName();
if(thisAccountName == null) {
return AFTER;
} else if(thatAccountName == null) {
return BEFORE;
} else {
return thisAccountName.compareTo(thatAccountName);
}
}
}
In this case sort=”natural” will sort using the above compareTo method which compares the accountName to sort.
Now suppose you want that for this specific mapping you want the collection to be sorted by, say, accountShortName. You will define a Comparator like this
package com.example;
//import statements
public class BankAccountShortNameComparator implements Comparator<BankAccount>{
public int compare(BankAccount o1, BankAccount o2) {
if(o1!=null && o2!=null && o1.getAccountShortName()!=null && o2.getAccountShortName()!=null) {
return o1.getAccountShortName().compareTo(o2.getAccountShortName());
}
if(o1!=null && o2!=null) {
return o1.compareTo(o2);
}
return 0;
}
}
Then your mapping will say something like this
<set name="bankAccounts" lazy="true" cascade="all,delete-orphan" inverse="true" sort="com.example.BankAccountShortNameComparator">
In this way Hibernate will use your custom Comparator to sort the set