Tento článek se zabývá využitím
UJO objektů v prostředí ORM frameworku
Hibernate. Jaký může být důvod nahradit klasické POJO objekty invazivnější alternativou? Výhodu vidím především v možnostech snadnějšího zpracování výsledků pomocí užitečného API a k tomu přijde vhod i jisté navýšení výkonu některých typů HQL dotazů.
Úvodem bych rád rozptýlil mýtus, že za UJO objekty je schovaná neprůhledná magie. UJO může být každý objekt, který implementuje interface
Ujo se čtyřmi metodami. Existuje více implementací, ale nyní si popíšeme
QuickUjo obsažený v
UJO Frameworku 0.91, který se vyznačuje snadnou použitelností a velkou rychlostí čtení i zápisu ve srovnání s Java reflexí.
Jak ten
QuickUjo tedy funguje, ptáte se? Uvnitř toho objektu je schovaný jediný atribut obsahující
pole objektů s délkou odpovídající počtu atributů objektu. Protože pro přístup k hodnotám objektu slouží konstanty zvané
UjoProperty, můžeme každé takové property přiřadit
index ukazující na jednu buňku z tohoto pole. Pokud tedy máme instanci UJO + UjoProperty, tak můžeme snadno získat i hodnotu, o přetypování se pak postará implementace UjoProperty. Není to jednoduché?
Typický příklad kódu pro čtení hodnoty:
String name = Person.NAME.getValue(person);
alternativní příklad použití rozšířené implementace
QuickUjoMid:
String name = person.get(Person.NAME);
Zajímavé bude srovnání výkonu UJO a POJO objektů v prostředí ORM frameworku
Hibernate, potřebujeme však znát, jak se ty UJO mapují. Můj kolega Tomáš Hampl, napsal elegantní řešení založené na implementaci rozhraní
PropertyAccessor, které je nyní k dispozici v UJO Frameworku 0.91. Vlivem
nedokonalosti Hibernate je třeba implementovat ještě odpovídající gettery, ty však Hibernate používá pouze při startu aplikace. Nic nám ovšem nebrání dopsat si také settery pro vlastní pohodlí a objekty používat jako běžné POJO. Ukázka hotové implementace UJO je
tady.
Specifikace alternativního accessoru v HBM souboru vypadá takto:
<hibernate-mapping
default-access = "org.ujoframework.hibernateSupport.UjoPropertyAccessor"
... >
Pokud se výdáte cestou anotací, použijte
@org.hibernate.annotations.AccessType( "org.ujoframework.hibernateSupport.UjoPropertyAccessor" )
a na místo fieldů anotujte gettery.
Podívejte se, jak dopadly benchmark testy:
| Hibernate akce | POJO [sec]
| UJO [sec] | Poměr |
| INSERT | 11,37 | 12,31 | 0,92 |
| SINGLE SELECT | 0,58 | 0,52 | 1,13 |
| EMPTY SELECTS | 152,53 | 94,30 | 1,62 |
| MULTI SELECT | 169,52 | 94,72 | 1,79 |
| UPDATE | 3,69 | 3,75 | 0,99 |
| DELETE | 210,14 | 140,27 | 1,50 |
Kompetentní výklad výsledků přenechám raději odborníkům na Hibernate v diskusi. Popis testovacího prostředí najdete
tady. Zdrojový kód testu lze stáhnout na
SourceForge.
Na závěr bych rád uvedl na pravou míru, že reálné navýšení rychlosti se projeví především u rychlých a dobře indexovaných SQL dotazů s přiměřenou mírou aplikační logiky. Pokud je odezva na SQL dotaz pomalá a nebo výsledek dotazu podléhá náročnému zpracování, úspora rychlosti se v kontextu ostatních událostí může vytratit.
Odkazy: