Как разрешить сбои при сохранении нескольких сущностей одновременно? - PullRequest
0 голосов
/ 16 мая 2018

Итак, у меня есть потенциально сотни строк, которые нужно вставить в базу данных.Нет валидации, проверяющей уникальность данных.

Однако в базе данных существует ограничение среди 3 столбцов, которые при объединении должны быть уникальными.Иногда эта уникальность не срабатывает, и вся операция сохранения завершается неудачей.

Есть ли способ игнорировать этот сбой при вызове Table::saveMany() и продолжать сохранять все другие записи?Может быть, зарегистрировать ошибку на потом, но все же продолжить сохранение остальных записей, вместо того, чтобы просто провалить всю операцию?

Ответы [ 2 ]

0 голосов
/ 16 мая 2018

Вы можете воспользоваться парой подходов к этой проблеме.

  1. Вместо использования Table::saveMany() выполните цикл и просто используйте Table::save() и сохраните записи о том, что не удалось, чтобы вы могли исследовать это позже.

  2. Разделите свою большую работу на меньшие партии. Если вам нужно сказать, скажем, 1000 записей, разделите это на 100 записей и используйте Table:saveMany() для каждого пакета. Таким образом, при сбое чего-либо только текущий пакет с ошибкой, а не весь процесс сохранения.

  3. Вид опасного (и рекомендуется НЕ ) - переопределить метод Table::save(), чтобы он не завершился ошибкой, даже если он не может хранить записи.

0 голосов
/ 16 мая 2018

Нет, нет, посмотрите описание API и исходный код для Table::saveMany(), он просто сохраняет все объекты в цикле, который остановит и откатит транзакцию в случае сбоя Table::save().

Записи будут сохранены в транзакции, которая будет откатываться, если какая-либо из записей не удастся сохранить из-за неудачной проверки или ошибки базы данных.

https://api.cakephp.org/3.6/class-Cake.ORM.Table.html#_saveMany

Если вы хотите разрешить сбои, то вы должны обработать это самостоятельно, сохранить каждую запись, перехватить возможные исключения и проверить результат операции сохранения.Вот быстрый и грязный пример, где $table - это таблица для сохранения, а $entities - массив сущностей:

$result = $table->getConnection()->transactional(
    function () use ($entities, $table) {
        foreach ($entities as $entity) {
            try {
                $result = $table->save($entity, ['atomic' => false]);
            } catch (\PDOException $exception) {
                $result = $exception;
            }

            if ($result !== true) {
                // log an error...
            }
        }

        return true;
    }
);

См. Также

...