Magento 2: ¿transacción de base de datos para varios objetos de modelo / modelo de recurso?

11

Si tengo una lógica que implica la actualización de varios objetos de modelo que actualizarán algunas tablas en la base de datos, ¿cómo proporcionar una transacción de base de datos para garantizar la integridad de los datos?

Paul
fuente

Respuestas:

22

Probablemente esté guardando un agregado de múltiples objetos conectados. Determine cuál de estos objetos es la raíz , por ejemplo:

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

Agregue la lógica de actualización en el modelo de recurso de la raíz y use una transacción allí.

Cómo usar transacciones

  1. Si desea guardar varias instancias de modelo, puede usar el modelo de transacción. Inyecte una fábrica de transacciones \Magento\Framework\DB\TransactionFactoryen su modelo de recurso y úsela así:

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

    Confirmar o deshacer se maneja automáticamente por el save()método.

  2. Alternativamente, puede usar transacciones directamente (si usa otras actualizaciones de la base de datos que no sean $model->save():

    $connection = $this->getConnection();
    $connection->beginTransaction();
    try {
        ...
        $connection->commit();
    } catch (\Exception $e) {
        $connection->rollBack();
        throw $e;
    }
    
Fabian Schmengler
fuente
¿Hay alguna forma compatible de guardar objetos múltiples mientras se usan repositorios? Internamente llaman save()métodos de modelos de recursos, por lo que cada uno de ellos se guardará en transacciones separadas. Los repositorios a menudo contienen cierta lógica de validación, por lo que generalmente se recomienda usarlos en lugar de save()métodos de modelo de recursos simples .
Bartosz Kubicki
1
@BartoszKubicki hay. Si dos modelos de recursos usan la misma conexión (lo que suelen hacer, la predeterminada), guardar la relación en afterSave () del primer recurso hará que se agreguen consultas a la misma transacción. Mira cómo se guardan los pedidos, línea por línea. OrderRepository :: save () es el punto de entrada.
vitoriodachef