Magento 2 - Transação de banco de dados para vários objetos de modelo / modelo de recurso?

11

Se eu tiver uma lógica que envolva a atualização de vários objetos de modelo que atualizarão algumas tabelas no banco de dados, como fornecer uma transação de banco de dados para garantir a integridade dos dados?

Paulo
fonte

Respostas:

22

Você provavelmente está salvando um agregado de vários objetos conectados. Determine qual desses objetos é a raiz , por exemplo:

               [order]              <------ this is the root
               /  |  \
billing_address   |   shipping_address
                  |
            order_items

Inclua a lógica de atualização no modelo de recursos da raiz e use uma transação lá.

Como usar transações

  1. Se você deseja salvar várias instâncias do modelo, pode usar o modelo de transação. Injete uma fábrica de transações \Magento\Framework\DB\TransactionFactoryno seu modelo de recursos e use-o assim:

    $saveTransaction = $this->transactionFactory->create();
    $saveTransaction->addObject($objectToSave);
    $saveTransaction->addObject($otherObjectToSave);
    ...
    $saveTransaction->save();

    A confirmação ou reversão é tratada automaticamente pelo save()método.

  2. Como alternativa, você pode usar transações diretamente (se você usar outras atualizações do banco de dados além de $model->save():

    $connection = $this->getConnection();
    $connection->beginTransaction();
    try {
        ...
        $connection->commit();
    } catch (\Exception $e) {
        $connection->rollBack();
        throw $e;
    }
Fabian Schmengler
fonte
Existe alguma maneira suportada de salvar vários objetos ao usar repositórios? Eles chamam internamente save()métodos de modelos de recursos, para que cada um deles seja salvo em transações separadas. Os repositórios geralmente contêm alguma lógica de validação; portanto, geralmente é recomendável usá-los em vez de save()métodos simples de modelo de recurso .
Bartosz Kubicki
1
@BartoszKubicki existe. Se dois modelos de recursos usarem a mesma conexão (o que geralmente fazem, a padrão), salvar a relação no afterSave () do primeiro recurso fará com que as consultas sejam adicionadas à mesma transação. Veja como os pedidos são salvos, linha por linha. OrderRepository :: save () é o ponto de entrada.
vitoriodachef