2015-09-20

Aliasy databázových tabulek v Ujorm

Jak se používají aliasy databázových tabulek v ORM frameworku Ujorm? Rád bych vyjasnil nejdříve některé základní pojmy (nejen) z frameworku Ujorm a jejich vzájemný vztah:
  • atribut / property - je vlastnost objektu, výklad můžeme demonstrovat na objektech typu POJO
  • vazba / relationship - speciální "atribut" objektu na jinou třídu typu POJO
  • propertyDescriptor - třída popisující vlastnosti "atributu" POJO (meta-model)
  • relationshipDescriptor - je propertyDescriptor, který popisuje "vazbu" mezi dvéma POJO (meta-model)
  • Key (dříve UjoProperty) - je propertyDescriptor frameworku Ujorm (immutable object)
  • Key<?,RelatedUjo> - je relationshipDescriptor frameworku Ujorm. Pokud je RelatedUjo perzistentní objekt ORM, tak instance Key popisuje vazbu na databázovou tabulku.

Při použití ORM se při startu aplikace sestavuje meta-model, kde každá databázová tabulka dostane pevně přiřazený svůj alias, to je vlastnost frameworku. Takový přístup sice vyhovuje mnoha databázovým dotazům, ale najdeme jistě případy, kdy se statickými aliasy nevystačíme, jsou to:
  1. rekurzivní dotazy (typicky filtrování zaměstnanců podle atributů nadřízeného)
  2. dvě relace na stejnou DB tabulky (například pro filtrování tabulky měnových kurzů, kde pro filtrování potřebujeme jeden alias na tabulky prodejní měny a jiný alias na tabulku nákupní měny). Tento případ zobrazuje následující class-model:
Pro popis odlišných aliasů se ve frameworku Ujorm využívá metoda Key.alias(String) pro Klíče typu relationshipDescriptor. Protože Klíče jsou vždy neměnné instance, tak metoda alias(String) vytváří ve skutečnosti nový kompozitní klíč, který obsahuje ten původní klíč společně a požadovaným alias jménem. Na příkladu měnových kurzů by pak mohla podmínka pro filtrování kurzu EUR/CZK vypadat takto:

import static Currency.CODE;

final Criterion<ExchangeRate> crn1, crn2, crn3;
crn1 = ExchangeRate.BUY.alias(
"aliasBuy").add(CODE).whereEq("EUR");
crn2 = ExchangeRate.SELL.alias(
"aliasSell").add(CODE).whereEq("CZK");
crn3 = crn1.and(crn2);


kde výrazy BUY a SELL jsou vazby (relationshipDescriptor) na číselník kurzových měn Currency. V servisních metodách však není dobré uvádět názvy alias explicitně a proto si připravíme nový kompozitní klíč ve třídě ExchangeRate:

public static final Key<ExchangeRate,Currency> SELL = ExchangeRate.$_DIRECT_SELL.alias(
"aliasSell");

kde výraz $_DIRECT_SELL představuje původní přímý klíč na tabulku prodejní měny. Vazba BUY si ponechá svůj původní alias, vazba SELL použije vždy explicitně zadaný alias. Java kód dotazu se pak zjednoduší na:

final Criterion<ExchangeRate> crn1, crn2, crn3;
crn1 = ExchangeRate.BUY.add(CODE).whereEq("EUR
")
crn2 = ExchangeRate.SELL.add(CODE).whereEq(
"CZK")
crn3 = crn1.and(crn2);


Při častějším použití dotazu si můžeme ve třídě ExchangeRate připravit dva nové kompozitní klíče ukazující přímo na ten kód měny, pak se sestavení podmínky dále zjednoduší na výraz:

final Criterion<ExchangeRate> crn1, crn2, crn3;
crn1 = ExchangeRate.BUY_CODE.whereEq("EUR
")
crn2 = ExchangeRate.SELL_CODE.whereEq(
"CZK")
crn3 = crn1.and(crn2);


Podobné řešení můžeme použít také pro případ rekurzivních SQL dotazů.

1 komentář:

Ponec řekl(a)...

> Proč se aliasy nezapisují ke klíčům pomocí anotace ?

Anotace nepokrývají dostatečně potřeby rekurzivních dotazů, protože tam může jeden klíč (typu relationshipDescriptor) nabývat více aliasů pro mnoho úrovňovou hierarchii (příkladem je třeba filtrování osob podle příjmení babičky).