Blog


Transacciones en Symfony2 con Doctrine

TRANSACCIONES EN SYMFONY2 CON DOCTRINE

01 / 08 / 2013 Symfony

No es extraño que desarrollando una aplicación web avanzada se nos presente el caso de tener que realizar un conjunto de operaciones en base de datos que deben ser tratadas como una unidad. A esto se denomina transacción. El caso más común es el de los movimientos bancarios entre dos cuentas, en el que no se debe descontar el dinero de la cuenta de origen si no se ha realizado el movimiento en la de destino.

En nuestro caso que desarrollamos con Symfony2, esta tarea resulta extremadamente sencilla gracias a la gestión de transacciones que proporciona Doctrine\DBAL\Connection, mediante los métodos beginTransaction(), commit() y rollback().

Hay dos formas de realizar la transacción con Doctrine, tal y como se explica en el capítulo correspondiente de la documentación oficial. Una es de la siguiente manera:


$conn->beginTransaction();
try {    
     // do stuff    
     $conn->commit();
} 
catch(Exception $e) {    
     $conn->rollback();    
     throw $e;
}

y una segunda forma, más concisa y en la que nos aseguramos de no olvidarnos revertir la transacción (rollback) en caso de excepción:


$conn->transactional(function($conn) {    
     // do stuff
});

El caso que comentábamos del movimiento en cuentas bancarias, desarrollado con Symfony2 y Doctine, resultaría de la siguiente manera:


$em = $this->getDoctrine()->getManager();
 
$em->getConnection()->beginTransaction();
 
try {
     $cuenta1 = $em->getRepository('VabadusBancoBundle:Cuenta')->find($id1);
     $cuenta2 = $em->getRepository('VabadusBancoBundle:Cuenta')->find($id2);

     $cuenta1->setSaldo($cuenta1->getSaldo() - 1200);
     $em->persist($cuenta1);

     $cuenta2->setSaldo($cuenta2->getSaldo() + 1200);
     $em->persist($cuenta2);

     $em->flush();
 
     $em->getConnection()->commit();
} 
catch (Exception $e) {
     $em->getConnection()->rollback();
     throw $e;
}



ARTÍCULOS RELACIONADOS