Kapitola 6. ORM nástroj Hibernate

Obsah

Úvod
Architektura Hibernate
Perzistentní třídy
Nastavení Hibernate pomocí rámce Spring
Mapování perzistentních tříd
Mapování tříd
Mapování vlastností tříd
Mapování asociací mezi perzistentními třídami
Mapování komponent
Mapování podporující polymorfismus a dědičnost
Mapování kolekcí
Práce s perzistentními objekty
Práce s perzistentními objekty prostřednictvím HibernateTemplate
Získávání objektů
Strategie výběru objektů
Transakční zpracování objektů
Závěr

Při vývoji aplikací bylo prokázáno, že se programováním kódu, který manipuluje s daty nad databází, zabere až 70% z času, který je pro daný projekt vyhrazen. Někteří odborníci jdou ještě dále a říkají, že se tato hranice pohybuje až někde kolem 90%. Rámec Hibernate poskytuje techniku pro převod dat z objektového modelu do relačního modelu a zpět, a tak dokáže usnadnit práci s daty nad databází a snížit čas potřebný pro naprogramování podobných metod.

Úvod

Jak jsem již uvedl, Hibernate je nástroj poskytující techniku pro objektově-relační mapování tříd jazyka Java na tabulky relační databáze (ORM). Krom toho, Hibernate poskytuje nástroje, jak s těmito daty manipulovat včetně objektově orientovaného jazyka (HQL), který na základě objektové notace dokáže uložená data z databáze vybírat v podobě objektů.

Hibernate dále poskytuje mechanismy pro transakční zpracování dat, polymorfní perzistenci, kešování, objektově orientované sestavování dotazů, vlastní datové typy a mnoho další funkcionality. Z řadou z nich se seznámíme v následujících podkapitolách. Hibernate poskytuje jednotné API pro práci s řadou databází a databázových serverů.

Aplikační rámec Spring [5] poskytuje podpůrnou funkcionalitu pro snadnou integraci a používání Hibernate společně s ním. Tyto technologie tvoří dvojici, která je v současné době na vrcholu popularity u JEE vývojářů, ale nejen u nich. Hibernate, stejně jako Spring, je vhodnou technologií pro použití i v desktopových aplikacích.

My si přiblížíme ORM nástroj Hibernate právě ve spolupráci s aplikačním rámcem Spring a tuto spolupráci si budeme ilustrovat na naší vzorové aplikaci. Aplikační rámec Spring nabízí podporu pro Hibernate v podobě rozhraní HibernateTemplate, HibernateInterceptor a v podobě Hibernate transakčního manažera. Tuto podporu si popíšeme v relevantních částech následujícího textu.

Architektura Hibernate

Následující obrázek ilustruje pozici Hibernate v naší vzorové aplikaci. Zde je potřeba říci, že naše aplikace je založena na třívrstvé architektuře. Jedná se o vrstvy prezentační, aplikační a datovou. Vrstva datová je tvořená sadou tříd, které se starají o manipulaci perzistentních dat nad databází. V našem případě je tato vrstva reprezentována vrstvou přistupující k datům, tzv. DAO vrstvou (Data Access Objects). Tato vrstva jako jediná komunikuje přímo s Hibernate.

Obrázek 6.1. Architektura aplikace

Architektura aplikace

Jak si můžeme všimnout, Hibernate je konfigurován pomocí nastavení uvedených v hibernate.properties a pomocí XML souborů reprezentujících mapování tříd na tabulky relační databáze. Hibernate poté komunikuje přímo s databází pomocí JDBC spojení.

Nyní si představíme útroby Hibernate a popíšeme si, jak tento nástroj funguje. Obrázek zachycuje jednotlivé vrstvy a rozhraní, se kterými bychom se měli seznámit nejdříve, pokud chceme Hibernate používat v naší datové vrstvě.

Obrázek 6.2. Architektura Hibernate

Architektura Hibernate

Hlavní pracovní jednotkou (motorem) Hibernate je sezení. Jedná se o implementaci rozhraní Session. Sezení zapouzdřuje JDBC spojení a představuje konverzi mezi objektovou a relační reprezentací dat. Sezení dále slouží jako továrna pro transakce a udržuje keš první úrovně. Objekty typu sezení je levné vytvořit a uvolnit, protože tohle se děje velmi často, zpravidla minimálně jednou během HTTP požadavku na webovou aplikaci.

Rozhraní Session a Transaction jsou využívána aplikací pro zajistění základních CRUD operací nad databázovými tabulkami. Na obrázku není zobrazené rozhraní Query, které patří na stejnou úroveň jako rozhraní Session a Transaction, a které je voláno v případě potřeby získávání dat z databáze.

Sezení je vytvářeno pomocí továrny sezení (rozhraní SessionFactory). Tato továrna je konfigurována pomocí nastavení uvedených v hibernate.properties a obsahuje zkompilované XML mapování tříd na tabulky relační databáze. Továrna sezení udržuje keš druhé úrovně. Objekt implementující toto rozhraní je poměrně drahé vytvořit, proto se v aplikaci většinou vyskytuje pouze jedna instance tohoto objektu. Pokud aplikace pracuje nad více databázemi, pro každou z nich musí existovat jedna továrna sezení.

JDBC spojení pro danou továrnu sezení připravuje poskytovatel spojení. Jedná se o množinu spojení (pool of connections), kterou poskytovatel spojení udržuje a tato jednotlivá spojení následně poskytuje továrně sezení.

Rozhraní Transaction je doporučené API, ale není povinné. Toto transakční API odstiňuje aplikační kód od implementace transakcí na nižší úrovni. Jedná se např. o JDBC transakce nebo JTA. Toto odstínění napomáhá přenositelnosti aplikace. Transakce vytváří transakční továrna. Transakční továrnou rozumíme implementaci rozhraní TransactionFactory. My je poté v aplikaci získáváme z Hibernate sezení.

Perzistentní třídy

Na perzistentní třídy Hibernate neklade, na rozdíl od jiných ORM rámců, žádné speciální nároky. Perzistentní třídy jsou obyčejné objekty, které musí obsahovat bezparametrický konstruktor. Je doporučováno, aby tyto třídy poskytovaly jednu vlastnost pro uchování hodnoty primárního klíče. Další omezení nejsou specifikována, takže tyto třídy zpravidla obsahují i další manipulační metody a často také implementují rozhraní Serializable za účelem jejich serializace.

Typickou ukázkou perzistentní třídy je třída SignPost ze vzorové aplikace, která uchovává data o odkazech na zajímavé akce, obchody a sportoviště.

public class SignPost implements Serializable {
  private String id;
  private String link;
  ...
  
  public String getId() {
   return id;
  }

  public void setId(String id) {
   this.id = id;
  }

  ....
}

Nastavení Hibernate pomocí rámce Spring

Abychom nesvazovali aplikační kód s "manuálně" nastavenými zdroji databázového spojení, poskytuje Spring možnost definovat tyto zdroje skrze jeho aplikační kontext, viz. aplicationContext-hibernate.xml. Objekty potom získají odkazy na tyto předem definované zdroje pomocí klasické syntaxe odkazů na třídy v aplikačním kontextu. Následující kód ukazuje definice instancí tříd LocalSessionFactoryBean a BasicDataSource potřebných pro vytváření objektů typu Hibernate SessionFactory.

<bean id="dataSource" 
      class="org.apache.commons.dbcp.BasicDataSource" 
      destroy-method="close">
   <property name="driverClassName" value="org.postgresql.Driver" />
   <property name="url" value="jdbc:postgresql://localhost:5432/sport" />
   <property name="username" value="jmeno" />
   <property name="password" value="heslo" />
</bean>

<bean id="sessionFactory" 
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean">
 <property name="mappingLocations" 
           value="classpath:/cz/morosystems/sportportal/pojo/*.hbm.xml"/>
 <property name="hibernateProperties">
  <props>
  <prop key="hibernate.dialect">org.hibernate.dialect.PostgreSQLDialect</prop>
  <prop key="hibernate.show_sql">true</prop>
  <prop key="hibernate.format_sql">true</prop>
  <prop key="hibernate.hibernate.generate_statistics">true</prop>
  <prop key="hibernate.cache.use_structured_entries">true</prop>
  <prop key="hibernate.cache.use_second_level_cache">false</prop>
  <prop key="hibernate.cache.provider_class">OSCacheProvider</prop>
  <prop key="hibernate.cache.use_query_cache">false</prop>
  </props>
 </property>
 <property name="dataSource" ref="dataSource"/>
</bean>

Objekt třídy LocalSessionBeanFactory je zodpovědný za vytváření továrny sezení rámce Hibernate. Třída LocaleSessionBeanFactory bývá instanciována jako jedináček a továrny sezení, které produkuje, bývají předávány pomocí referencí do všech služeb, které je potřebují. Defaultně se však jedná o proxy objekty, které nechávají tyto služby přistupovat k datům skrze továrnu sezení a její metodu getCurrentSession(), ale které mohou participovat na transakcích řízených aplikačním rámcem Spring. Navíc může metoda getCurrentSession() pracovat se sezením řízeným objektem typu OpenSessionInViewFiltr skrze uživatelské požadavky. Více o transakcích i třídě OpenSessionInViewFilter se dozvíme v podkapitolách 3.3.2. a 3.4.

Na příkladu vidíme možné nastavení továrny sezení, tak jak je máme řešené v naší aplikaci. Tímto nastavením říkáme, že XML soubory reprezentující mapování tříd na tabulky databáze se nacházejí v balíku cz.morosystems.sportportal.pojo a mají příponu hbm.xml. Říkáme, že používáme databázový server PostgreSQL a definujeme JDBC ovladač, který bude komunikaci s tímto serverem obstarávat. Dialekt definuje použitou syntaxi generovaných SQL dotazů.

Dále říkáme, že do logů se mají vypisovat formátované SQL dotazy, že Hibernate má sbírat data o svém běhu pro potřeby statistik a nastavujeme kešování druhé úrovně a kešování dotazů. Pro keš druhé úrovně definujeme tzv. poskytovatele, který bude naši keš řídit. Stejně jako Hibernate má mnoho dalších voleb, tak i tohoto poskytovatele můžeme dále konfigurovat, ale to již není předmětem této práce.

V této podkapitole jsme se seznámili s ORM nástrojem Hibernate, jeho konfigurací a představili jsme si řadu pojmů, o které se budeme dále opírat. Nyní se podrobně seznámíme s mapováním perzistentních tříd na tabulky relační databáze.

Komentáře

komentoval: Bot, dne: 28. 05. 2008, 08:46

Teda prekladat session jako sezeni, to me vzdycky zvedne ze zidle… Ale jinak dobry popis.

Vložit komentář

Můžete používat značkovací jazyk Texy!


Jméno:
E-mail:
Url:
Komentář:
1 + 2 =
 
MoroSystems, s.r.o.