Transakční zpracování objektů

S tématem transakcí ve spojení s Hibernate také souvisí téma strategií ukládání dat z paměti do databáze (Flushing the Session), které si nyní představíme.

Změny na perzistentních objektech v perzistentním stavu, tedy na těch, které jsou právě asociovány s Hibernate sezením, nejsou ihned ukládány z paměti na disk. Hibernate se tak snaží snížit počet dotazů nad databází a tím snížit propustnost sítě. Hibernate ukládá data do databáze pouze v následujících případech.

Když transakce byla úspěšně dokončena (commit)

Základní nastavení. Umožňuje dělat mnohé změny na perzistentních objektech, které budou promítnuty do databáze, jakmile je úspěšně dokončena databázová transakce.

V případě volání dotazu, který vyžaduje, aby všechna data byla uložena

Hibernate neukládá data do databáze při každé změně, ale provádí je v paměti. Nicméně, pokud je volán dotaz, který může být tímto chováním ovlivněn, Hibernate synchronizuje stav paměti s databází a až poté je tento dotaz proveden.

V případě explicitního volání Session.flush()

V případě explicitního volání metody flush() nad Hibernate sezením dojde k synchronizaci paměti a databáze.

Toto chování se dá kontrolovat za běhu nastavením způsobu synchronizace pomocí Session.flushMode(). Hodnota FlushMode.AUTO nastaví synchronizaci na vlastnosti popisované výše. FlushMode.COMMIT nastaví synchronizaci pouze po úspěšném ukončení transakce, což ale může způsobovat chybné výsledky některých dotazů. FlushMode.NEVER potom povolí synchronizaci pouze v případě explicitního volání Session.flush().

Pokud používáme transakce ve spojení s Hibernate a aplikačním rámcem Spring, používáme je skrze transakčního manažera. Transakčním manažerem myslíme implementaci rozhraní PlatformTransactionManager, poskytované aplikačním rámcem Spring, které nakonfigurujeme následovně, viz. aplicationContext-hibernate.xml a applicationContext-business.xml.

<bean id="transactionManager" 
      class="org.springframework.orm.hibernate3.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory"/>
</bean>

<bean id="transactionInterceptor"
 class="org.springframework.transaction.interceptor.TransactionInterceptor">
 <property name="transactionManager" ref="transactionManager"/>
 <property name="transactionAttributeSource">
  <value>
  cz.....managers.CompetitorManager.*=PROPAGATION_REQUIRED
  cz.....sportportal.managers.GuidePostCategoryManager.*=PROPAGATION_REQUIRED
  cz.....sportportal.managers.RegionManager.*=PROPAGATION_REQUIRED
  cz.....sportportal.managers.SportManager.*=PROPAGATION_REQUIRED
  cz.....sportportal.managers.UserManager.*=PROPAGATION_REQUIRED
  cz.....sportportal.managers.CompetitorManager.*=PROPAGATION_REQUIRED
  </value>
 </property>
</bean>

<bean 
class="org.springframework.aop.framework.autoproxy.BeanNameAutoProxyCreator">
  <property name="beanNames" value="*Manager" />
  <property name="interceptorNames">
    <list>
      <value>debugInterceptor</value>
      <value>performanceMonitorInterceptor</value>
      <value>transactionInterceptor</value>
    </list>
  </property>
</bean>

Aplikační rámec Spring nám nabízí deklarativní správu transakcí, jak si můžete všimnout na našem příkladu.

Naším transakčním manažerem je ve skutečnosti HibernateTransactionManager, který nastavuje Hibernate sezení, poskytované továrnou sezení, do vlákna, které zpracovává uživatelský požadavek na aplikaci. Toto sezení je pod správou tohoto transakčního manažera a je poskytnuto pro práci jak třídě HibernateTemplate, tak i třídám OpenSessionInViewFilter a OpenSessionInViewInterceptor. Od této chvíle se mohou tyto třídy účastnit transakčního zpracování dat.

Transakční zpracování je nastaveno na všechny metody manažerů aplikační vrstvy s nastavením uvedeným v deklaraci transakčního interceptoru. Na metodách se dá definovat, jakou část kódu transakce pokrývají apod. V našem případě PROPAGATION_REQUIRED říká, že v jedné transakci bude za běžného stavu všechen kód dané metody manažera. Pokud transakce neexistuje, pak se vytvoří, pokud již transakce existuje, tato metoda se bude na jejím běhu podílet. Samozřejmě můžeme specifikovat i další parametry transakcí, ale to je již nad rámec našeho textu.

Pokud nyní použijeme metodu getHibernateTemplate().find(), proběhne tato metoda v transakci.

Představme si však, že pokud jsme modifikovali v této transakci nějaké perzistentní objekty a jejich stav byl synchronizován s databází (nastaven FlushMode.AUTO nebo synchronizace byla vynucena explicitně) a naše transakce poskytovaná transakčním manažerem bude neúspěšná, nad databází se provede rollback, ale objekty v paměti zůstanou modifikované. Poté nezbývá nic jiného, než udělat getHibernateTemplate().clear(), což vymaže tato data z paměti a nasledně se budou postupně do paměti dostávat správná data z databáze.

O transakcích se toho dá také napsat mnohem více, než jsme zde uvedli. My jsme si zde transakční zpracování objektů pouze představili a řekli jsme si, jak jej můžeme používat. Více se můžeme dozvědět v dokumentacích k Hibernate [12] i k aplikačnímu rámci Spring [5].

Komentáře

Téma neobsahuje žádné komentáře.

Vložit komentář

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


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