Dědičnost v hibernate vs Proxy

Jedním ze základních stavebních kamenů v OO návrhu je dědičnost. Nikoho tedy nepřekvapí, že tuto vlastnost nabízí i ORM a tedy i Hibernate.

Při použití dědičnosti v Hibernate a současném používání Proxy ovšem nastávají problémy.

Proxy umožňuje mít referenci na objekt aniž by cílový objekt byl z databáze skutečně načten. Velký smysl má hlavně u vazeb typu 1 ku X (kde X může být jak 1 tak i více než 1).

Uvažujme tento příklad:

public class Smlouva {
    private Zakaznik zakaznik;
}

V případě, že přistoupíte k objektu Smlouva, musí hibernate načíst i objekt Zakaznik. Pokud ovšem použijete Proxy, je použit zástupný objekt, který načte objekt Zazkaznik až při prvním přistupu k němu.

K vytvoření proxy Hibernate použivá knihovnu CGLib a vytvoří objekt odvozený od původního – tedy Zakaznik. Výsledek pak vypadá takto:
Zakaznik$$EnhancerByCGLIB$$933ae557.

Uvažujme teď jiný případ. Vytvořme novou třídu:

class FiremniZakaznik extends Zakaznik {
     public String getIC() { ... };

Při jejím prvním načtení je vrácen objekt typu rodič (tj. Zakaznik), který je zastoupen vygenerovanou proxy. Proxy ovšem nedědí od FiremniZakaznik, a tak nemá nově přidané metody (přetížené metody samozřejmě fungují). Z čistě objektového přístupu je všechno v pořádku.

Pokud se pokusíte přetypovat proxy na FiremniZakaznik dostanete oblíbenou ClassCastException (případně NoSuchPropertyException).

Na stránkách hibernate doporučují použít visitor pattern.

Pro ty z vás, kteří stejně jako my, používáte MVC framework a používáte tzv. expressions (#{smlouva.zakaznik.IC}) není použití tohoto vzoru ideální.

Řešením je přidat metodu getThis().
Upravíme tedy zákazníka tak, aby obsahoval následující:

class Zakaznik {
    public Zakaznik getThis() { return this; }
}

Pak je možné u položek, které nejsou v rodičovské třídě (a jiné řešení by bylo příliš složité), použít výraz #{smlouva.zakaznik.this.IC}.

Obvykle nepoužíváme ve výrazech přímo metodu getThis(), ale při vytváření parametrů pro view předáváme objekt zbavený proxy.

Napsat komentář

Vaše emailová adresa nebude zveřejněna. Vyžadované informace jsou označeny *