neděle 17. září 2006

Ze života Hibernate

(Původně vyšlo 17. září 2006, aktualizováno 13. února 2008)
Tenhle spot bych chtěl pojmout jako takovou symbolickou omluvu Marovi, kterému jsem tvrdil, že v Hibernate (což je řekněme nástroj pro ulehčení databázového programování v Javě) se dá stejných výsledků jako pomocí konfigurace XML soubory dosáhnout také anotacemi podle JSR-220 (EJB 3.0 persistence). Není to pravda.

Mějme příklad objednávka-produkty (položky objednávky), tedy vztah many-to-many. Z hlediska Javy ho budou tvořit dva objekty (Objednavka a Produkt), které budou mít (obousměrný) vztah many-to-many , v databázi vyjádřený tabulkami objednavka a produkt a vazební tabulkou objednavka_produkt, obsahující cizí klíče (objednavka_id a produkt_id). Potud žádný problém.
Ovšem v reálném světě je často potřeba mít ve vazební tabulce další popis vztahu, třeba počet objednaných kusů. A tady už problém je, protože takový vztah popsat Hibrenate JSR-220 anotací (@ManyToMany) neumí. Podle vývojáře Hibernate Annotations Emmanuela Bernarda tohle mělo fungovat ve verzi 3.2.1, ale nefunguje a podle jeho posledního vyjádření ani hned tak nebude.

Co s tím? Dá se to obejít samozřejmě tak, že vztah many-to-many dekomponujeme na dva vztahy many-to-one. Z vazební tabulky vyrobíme entitu (ObjednavkaPol), která bude mít složený primární klíč z cizích klíčů do tabulek objednavka a produkt (se vztahem many-to-one). Způsobů jak toho dosáhnout je víc, ale jen jediný se mi povedlo spolehlivě rozhýbat v Hibernate 3.2.5 (ve verzi 3.2.0 tomu bylo ovšem jinak :)

K vytvoření složeného primárního klíče vyrobíme novou třídu (ObjednavkaPolId), necháme ji implementovat rozhraní Serializable (s překrytím metod hashCode() a equals()) , označíme ji anotací @Embeddable a přidáme do ní dva členy typu Objednavka a Produkt, které označíme anotacemi @ManyToOne a @JoinColumn(name="xxx_id", nullable=false).

Třídu ObjednavkaPol označíme anotací @IdClass(ObjednavkaPolId.class), přidáme do ní všechny property z ObjednavkaPolId, které tvoří primární klíč, oanotujeme je jako @Id a opět jako @ManyToOne a @JoinColumn(name="xxx_id", nullable=false).

To, že máme položky klíče ve dvou třídách se na první pohled může například proti řešení s anotací @EmbeddedId zdát neohrabané, ale není to tak hrozné. Části klíče jsou rovnou součástí entity a pokud potřebujeme entitu vyhledat prostřednictvím primárního klíče, využijeme ObjednavkaPolId.

Žádné komentáře:

Okomentovat