tiny ‘n’ smart
database layer

Odkazy: dibi | API reference

Oznámení

Omlouváme se, provoz fóra byl ukončen

indikace transakce ?

před 10 lety

wdolek
Člen | 331

snazim se vyporadat s „problemem“ transakci. pouzivam dibi s Nette. mam dve modelove tridy – prvni z nich reprezentuje zakladni udaje o clanku, druhy objekt (a druha tabulka) reprezentuje obsah clanku ve vice jazycich.
(tabulka „article“ obsahuje nejake udaje o case, atd…, „article_text“ obsahuje obsah clanku pro „cs“ a „en“)

je zrejme, ze obe modelove tridy jsou propojeny – „Article“ obsahuje instanci objektu „ArticleText“. na obou objektech je metoda save(), ktera se rozhodne, zda-li udelat insert nebo update. budu uvazovat, ze volam insert().
jakym zpusobem mam navrhnout aplikaci s pouzitim transakci, abych ale zaroven mohl volat ArticleText::save() ?… uvedu priklad

<?php
// Article
function insert() {
  $db = self::getDb();

  $db->begin(); // zacatek transakce
  $db->begin('clanek'); // zalozeni savepointu

  try {
    $db->insert( ... )->execute(); // vlozeni obecnych udaju clanku

    // zavolani save() na obsahu, pokud vrati FALSE, vyvolame vyjimku, ktera smeruje k rollbacku clanku
    if (!$this->textContent->save()) {
      throw new Exception();
    }

    $db->commit('clanek'); // uvolneni savepointu
    $db->commit(); // commit transakce

    return TRUE;
  } catch (Exception $e) {
    $db->rollback('clanek'); // navrat savepointu
    $db->rollback(); // celkovy rollback

    return FALSE;
  }
}

// ArticleText
function insert() {
  $db = self::getDb();

  $db->begin(); // zacnu transakci - nevim totiz, jestli v ni sem (volani z Article) nebo ne (volani primo ArticleText)
  $db->begin('obsah'); // savepoint

  try {
    foreach ($this->text as $lang => $t) {
      $db->insert( ... )->execute(); // vlozeni obsahu
    }

    $db->commit('obsah'); // uvolneni savepointu
    $db->commit(); // commit transakce

    return TRUE;
  } catch (Exception $e) {
    $db->rollback('obsah'); // navrat savepointu
    $db->rollback(); // celkovy rollback

    return FALSE;
  }
}
?>

… uvedeny kod nefunguje :P … ve volani insert na objektu ArticleText totiz znovu zacinam transakci… sice to nehazi chybu, ale nic se neprovede :P… jak se neco takoveho da resit?

pouzivam PostgreSQL

predem diky za jakoukoliv radu

před 10 lety

viktorc
Člen | 21

Podla DibiConnection.php by malo druhe volanie begin bez uvedenia savepointu (teda v ArticleText::insert) vyhodit DibiException(‚There is already an active transaction.‘). Ta ta vykopne do Article::insert, kde spravis rollback a nic sa neulozi.

Skus zachytavat vynimku aj v ArticleText::insert na begin() a podla toho zistis, ci si, alebo nie si v transakcii. Nasledne (po ulozeni obsahu clanku) podla toho volaj/nevolaj aj celkovy commit/rollback.

před 10 lety

wdolek
Člen | 331

viktorc: ja sem nakonec „jednoduse“ pouzil rozhodovani na zaklade „inTransaction()“ a pro jistotu toto rozhoduji i v objektu clanku – kdyby nahodou nekdy v budoucnu clanek obsluhovala jina vec a bylo vse v transakci.