Vydělávej až 160.000 Kč měsíčně! Akreditované rekvalifikační kurzy s garancí práce od 0 Kč. Více informací.
Hledáme nové posily do ITnetwork týmu. Podívej se na volné pozice a přidej se do nejagilnější firmy na trhu - Více informací.

Spring - Transakcie v Jave

V predchádzajúcom lekcii, Java spustenie - Programové argumenty , sme si predviedli spustenie s programovými argumenty.

Transakcia je postupnosť databázových príkazov, ktoré sa vykonajú v jednom behu. Ak sa nejaký z nich nevykoná (napr. Neprejde cez integritné obmedzenia), nevykoná sa žiadny z príkazov (všetko alebo nič).

Základné pojmy

  • BEGIN - začne transakciu
  • COMMIT - všetky príkazy sa vykonajú postupne
  • ROOLBACK - nastala chyba v nejakom príkazu. Dáta sa vráti do pôvodného stavu (pred začiatkom transakcie).

ACID

Pravidlá, čo musí každá transakcia spĺňať.

  1. Atomicita (Atomicita) - transakcia prebehne buď celá alebo neprebehne vôbec
  2. Consistency (konzistencia) - pri zapísanie (vyhotovenie príkazov) nie je porušené žiadne integritné obmedzenie
  3. Isolation (izolovanosť) - transakcia je čierna skrinka, operácia sa navzájom v rámci viac transakcií neovplyvní
  4. Durability (trvalosť) - raz uložené zmeny nezmizne a sú uložené natrvalo

Spring

Transaction Manager

Riadi prácu s transakciami. V praxi sa s ním stretnete len výnimočne. Ide skôr o pochopenie princípu fungovania.

public interface PlatformTransactionManager {

    TransactionStatus getTransaction(TransactionDefinition definition) throws TransactionException;

    void commit(TransactionStatus status) throws TransactionException;

    void rollback(TransactionStatus status) throws TransactionException;
}

Najskôr si hovoríte, kde je metóda na začatie transakcie (begin). Metóda getTransaction je veľmi špecifická. Ak transakcia existuje vráti ju, ak nie vytvorí ju. Transakciu tu reprezentuje trieda TransactionStatus.

Nastavenia vo Spring

Je potrebné zaviesť transakčné manager do aplikačného kontextu:

<tx:annotation-driven transaction-manager="transactionManager"/>
<bean id="transactionManager"
      class="org.springframework.jdbc.datasource.DataSourceTransactionManager">
  <property name="dataSource" ref="dataSource"/>
</bean>

<tx: annotation-driven... nám zaistí, že Spring bude čítať anotácie (@Transactional). Spring zariadi všetku špinavú prácu za nás (vytvorenie proxy tried ...).

Najskôr si všimnete, že je potreba transactionManager odovzdať datasource. DataSource slúži pre pripojenie aplikácie k databáze. Sedláčka povedané v ňom nadefinujete adresu, meno a heslo a on už sa postará o pripojení. Viac sa môžete dočítať v dokumentácii k datasource

Bez anotáciu

Ak poznáte princíp fungovania, neprekvapí vás nečakané situácie. Pri použití nástroja na integritné testovanie sme zistili, že mechanizmus pomocou anotácií nepracuje podľa očakávania. Vytvorili sme teda abstraktné triedu, ktorá mala na starosti riadenie transakcií.

Integračné test

Testuje integráciu (funkčnosť prepojenie) viac komponentov dohromady.

Príklad: "Mám dáta v nejakom stave. Vykonám postupnosť príkazu naprieč aplikácií. Dáta sa zmenili podľa očakávania.

public abstract class AbstractTransactionTest {
  @Autowired
  private DataSourceTransactionManager manager;

  private TransactionStatus transactionStatus;

  @Before
  public final void beforeTest() {
    //typ transakce
    int propagationBehavior = DefaultTransactionDefinition.PROPAGATION_REQUIRED;
    // vytvori inicialni stav transakce
    DefaultTransactionDefinition initStatus = new DefaultTransactionDefinition(propagationBehavior);
    // aktivuje transakci
    transactionStatus = transactionManager.getTransaction(initStatus);
  }

  @After
  public final void afterTest() {
    manager.rollback(transactionStatus);
  }

Princíp je jednoduchý. Na začiatku testu sa začne transakcie. Po dokončení testu sa vykoná rollback.

Možno si hovoríte, prečo sa vykonáva rollback ... Ako sme sa dočítali v predchádzajúcich tutoriáloch, testy by sa nemali navzájom ovplyvňovať. Ak by sa dostala dáta do databázy, mohlo by dôjsť ku komplikáciám. Iný test by mohol začínať s dátami v stave, ktorý neočakáva.

Anotácie

@Transactional (propagation ...) V praxi Vám táto anotácia bohato postačí na všetku prácu s transakciami.

  • Propagation. REQUIRED - DEFAULT. Ak existuje transakcia, je prevzaté. Ak neexistuje, je vytvorená nová.
  • Propagation. MANDATORY - Ak existuje transakcie, je prevzaté. Ak neexistuje, vyhodí sa výnimka.
  • Propagation. NOT_SUPPORTED - Pozastaví bežiaci transakciu a vykoná kód netransakčné.
  • Propagation. SUPPORTED - Ak existuje transakcie, je prevzaté. Ak neexistuje, pustí sa kód netrasakčně.
  • Propagation. REQUIRES_NEW - Ak existuje transakcie, je pozastavená a vytvorí sa nová. Ak neexistuje, vytvorí sa nová.
  • Propagation. NEVER - Ak existuje transakcie, vyhodí výnimku. Inak sa vykoná netransakčné.
  • Propagation. Nested - Ak existuje transakcie, pustí novú (beží 2 paralelne). Ak neexistuje, vytvorí sa.

Jednoduché použitie

Časť kódu, ktorá má bežať v transakcii je označená danú anotácií (@Transactional).

@Transactional
public class CarService {
  public void myTransactionMethod() {}
}

Ako to funguje?

Princíp si ukážeme na imaginárnom príklade.

Anotácia nám zaístí, že sa nad danou triedou vytvorí proxy objekt ( proxy pattern).

Daná metóda, čo má bežať v transakcii, je zaobalené do podobného bloku:

TransactionalManager txManager;

public void myTransactionMethod(Object o) {
  try {
    TransactionStatus  status = txManger.getTransaction(definition);
    myTransactionMethod();
    txManager.commit(status);
  } catch (Exception e) {
    txManager.roolback(status);
  }

}

pozn. Príklad vysvetľuje len princíp fungovania, v reále je to zložitejšie.

Kedykoľvek potom niekto zavolá danú triedu, zavolá sa tento proxy objekt a vykoná sa daný kód v transakcii.

Ak všetko prebehne v našej metóde v poriadku (nevyhodí sa výnimka), transakcie manager vykoná commit transakcie. Všetky príkazy sa vykonajú nad databázou.

Pokiaľ v našej metóde dôjde k chybe (napr. Kontrola duplicity záznamu vyhodí výnimku), manager vykoná roolback. Všetky príkazy po štarte transakcie sa zahodí.

Architektúra: Kde riadiť transakciu?

Čiže kde použiť @Transactional. Pokiaľ máte trojvrstvovú architektúru aplikácie, transakcia sa zvyčajne riadi na vrstve služby.

3-vrstvová architektúra - Java - Pre pokročilých

Trojvrstvová architektúra aplikácie:

  • Controller - slúži pre komunikáciu s front-end. S tým čo vidí používateľ.
  • Service - vrstva, kde prebiehajú hlavné výpočty aplikácie (tu sa používa @Transactional)
  • DAO - vrstva pre prístup do repository (databázy)

 

Predchádzajúci článok
Java spustenie - Programové argumenty
Všetky články v sekcii
Java - Pre pokročilých
Článok pre vás napísal Petr Kunčar
Avatar
Užívateľské hodnotenie:
Ešte nikto nehodnotil, buď prvý!
Nejlepší práce je taková, která vás baví. Nejlepší manželka je taková, co vás chápe. Nejlepší rodina je taková, co vás podporuje. Nejlepší relax je v přírodě. Nejlepší, co pro svět můžeš udělat, je řešit problémy rychle a elegantně.
Aktivity