Dnes výjímečně nebudu publikovat svůj příspěvek, ale příspěvek mého současného kolegy Vaška Hrdiny. Řešený problém mi přišel natolik zajímavý, že jsem ho požádal o publikaci na mém blogu.
Řazení v Hibernate
Pro řazení přes Criteria API existuje metoda
addOrder():
crit.addOrder(Order.asc(DOdatovy_objekt.POLE)); //vzestupně
crit.addOrder(Order.desc(DOdatovy_objekt.POLE)); //sestupně
pro HQL je možné použít klauzuli
order by:
createQuery("from " + DOdatovy_objekt.class.getSimpleName() + " as do order by do." + DOdatovy_objekt.POLE); //vzestupně
createQuery("from " + DOdatovy_objekt.class.getSimpleName() + " as do order by do." + DOdatovy_objekt.POLE + " desc"); //sestupně
Řazení NULL hodnot
Problém ale nastává pro řazení NULL hodnot.
Pokud je políčko NULL, pak jej MSSQL řadí na první místo, Oracle oproti tomu jako poslední. Ne vždy můžeme použít řazení až na aplikačním serveru (např. při tisku velké sestavy, kdy musíme získávat data stránkovaně), přesto je třeba řadit na všech DB stejně.
Nepřišel jsem na vhodný způsob, jak toto vyřešit, hibernate JIRA obsahuje
požadavek, který se tohoto týká. Jediný způsob, na který jsem byl schopný přijít je řešení přes
formule.
Jedná se o to, že do mapovaného objektu přidáte políčko (stačí políčko, nemusí mít ani getter), které se naplní předem definovaným SQL příkazem (pozor, jedná se skutečně o SQL, je tedy třeba hlídat mezidatabázovou kompatibilitu). Podle něj se dá řadit. A pokud zajistíte, aby se v políčku vyskytovaly takové znaky, aby se řadilo podle Vašich potřeb (typicky NULLy půjdou jako první), je vyhráno.
Následující příklad ukazuje, jak řadit písmeno orientačního čísla tak, aby pokud není vyplněné, bylo první (tedy např. 16, 16a, 16b...):
@Entity
@Table(name = "adresa")
public class DOadresa extends cz.marbes.daisy.modules.x.mdo.DOGadresa {
@Formula("case when PISMENO_CO is null then ' ' else PISMENO_CO end")
private String pismenoCONotNull;
}
V kódu, který potřebuje takto řadit, pak stačí uvést:
crit.addOrder(Order.asc("pismenoCONotNull")); //pro Criteria API
createQuery("from " + DOdatovy_objekt.class.getSimpleName() + " order by pismenoCONotNull"); //pro HQL
Políčko
pismenoCONotNull je pak normálně přístupné, jako kterékoliv jiné políčko, obsahuje buď mezeru nebo obsah pole PISMENO_CO.