Oznámení
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.