Нужен ли save () при использовании commit ()?

Я понял, что save() и commit() будут выполнять одну и ту же транзакцию базы данных дважды.

Например.

if (isset($userId)) 
{
    $update = true;
    $user->load(array('id=:id', array(':id' => $userId)));
}

$user->designation_id = $f3->get('POST.designation_id');
$user->firstname = $f3->get('POST.firstname');
$user->lastname = $f3->get('POST.lastname');

$user->save(); //update made to users table

$this->db->begin();

foreach ($userTeams as $teamId) 
{
     $sqlArray[] = sprintf('INSERT INTO %s (internal_team_id, users_id) VALUES (%d,%d)', 'users_internal_team', $teamId, $user->get('_id'));
}
$this->db->exec($sqlArray); //update made to some other table

$this->db->commit();

echo $this->db->log();
die();

Журнал покажет мне следующие транзакции, выполненные в таблице "users":

...other log information related to other tables..

UPDATE `users` SET `designation_id`=3,`lastname`='Mali' WHERE `id`=134 Wed, 11 Apr 2018 11:39:20 +0200 (0.5ms) 
UPDATE `users` SET `designation_id`=3,`lastname`='Mali' WHERE `id`=134

Значит ли это, что я могу удалить $user->save(), а $this->db->commit() сделает то же самое со мной?

commit() можно использовать только в SQL. Поскольку DB Mapper работает и для других движков, существует метод save().
sascha 11.04.2018 11:49

Нет, вы должны сохранить данные. Коммит просто применяет набор save(), выполненных между BeginTransaction и EndTransaction, или, если что-то пойдет не так между Begin и End, все эти изменения откатываются

RiggsFolly 11.04.2018 11:50

I предполагать, что save действует в таблице базы данных, тогда как commits отмечает транзакцию как завершенную. Это означает, что после отката ваша база данных выглядит так, как будто транзакции никогда не было. Так что они не делают то же самое, один сохраняет в таблицу, другой завершает игру при успехе.

k0pernikus 11.04.2018 11:51

Но когда я удаляю часть user-> save (), она тоже работает нормально, и выполняется только одна транзакция обновления. В то время как с user-> save () и commit () выполняются две транзакции обновления.

Azima 11.04.2018 11:52

Не совсем понятно, что происходит в этом коде. Но я предлагаю вам ознакомиться с концепцией транзакции в руководстве.

RiggsFolly 11.04.2018 11:53

Ну, на самом деле вы только save, $user, очевидно, Вне транзакции, затем вы идете и делаете несколько Raw SQL INSERTS внутри транзакции. Не зная, что происходит до того, как этот код будет запущен, трудно понять, что вы на самом деле здесь делаете.

RiggsFolly 11.04.2018 11:54
0
6
114
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

TL; DR

save() и commit() - две разные вещи, поэтому не стоит пропускать save().

Фон SQL

В SQL вы можете написать:

UPDATE users SET designation_id=3,lastname='Mali' WHERE id=134;
INSERT INTO users_internal_team (internal_team_id, users_id) VALUES;(999,134)

Или вы можете написать:

BEGIN;
UPDATE users SET designation_id=3,lastname='Mali' WHERE id=134;
INSERT INTO users_internal_team (internal_team_id, users_id) VALUES;(999,134)
COMMIT;

Разница в том, что в первом примере, если во время выполнения оператора INSERT произошла ошибка (например, дублированная запись), оператор UPDATE не будет отменен (он же «откат»), тогда как во втором примере это произойдет.

В F3 эквивалентными примерами могут быть:

$db->exec('UPDATE users etc.');
$db->exec('INSERT INTO users_internal_team etc.');

а также

$db->begin();
$db->exec('UPDATE users etc.');
$db->exec('INSERT INTO users_internal_team etc.');
$db->commit();

Обратите внимание, что если вы передадите массив операторов методу exec(), они будут автоматически встроены в транзакцию:

$db->exec([
  'UPDATE users etc.',
  'INSERT INTO users_internal_team etc.',
]);
// automatically calls $db->begin() and $db->commit()

Ваш код

В вашем коде вы вызываете user->save(), который запускает либо $db->exec('INSERT etc.'), либо $db->exec('UPDATE etc.'), в зависимости от результата предыдущего $user->load().

Это одно заявление.

Тот факт, что два идентичных оператора появляются в журнале и что одно из них все еще отображается, когда вы пропускаете вызов $user->save(), позволяет мне думать, что $sqlArray должен содержать тот же самый оператор.

Возможно, я ошибаюсь в последнем пункте, но в любом случае последовательность, которую вы используете, верна.

У $sqlArray нет этого утверждения ... Я проверил его и перепроверил ... Не знаю, что это вызывает ... Но, похоже, только commit() выполнил работу save() ... удаление save() дает ожидаемый результат .

Azima 18.04.2018 07:15

Это действительно странно. Я только что создал тестовый пример, но не смог воспроизвести вашу проблему. Вы используете старую версию? Также вы должны убедиться, что запрос действительно выполняется дважды. Его можно было выполнить один раз и дважды зарегистрировать. Кстати, я обновил ответ, чтобы уведомить, что при передаче массива операторов в exec() автоматически выполняются $db->begin() и $db->commit().

xfra35 18.04.2018 10:37

Я определил триггер на обновление / вставку для этой таблицы, и именно так я обнаружил, что оператор выполняется дважды.

Azima 18.04.2018 13:29

Спасибо за обновленный ответ. Действительно оценил это.

Azima 18.04.2018 13:29

Другие вопросы по теме