I’m running a batch process in Symfony 5.4.48 (PHP 7.4.30, Doctrine ORM 2.20.3) where I need to handle database transactions per iteration. If a business condition fails, I want to rollback the transaction and continue to the next item. However, after a rollback, the next iteration fails with:
Transaction commit failed because the transaction has been marked for rollback only.
Here’s a simplified version of my code:
<?php
foreach ($items as $item) {
$em = $doctrine->getManager();
$connection = $em->getConnection();
$connection->beginTransaction();
try {
// ... business logic ...
if ($shouldRollback) {
$connection->rollBack();
$doctrine->resetManager();
continue;
}
$connection->commit();
} catch (Throwable $e) {
if ($connection->isTransactionActive()) {
$connection->rollBack();
}
$doctrine->resetManager();
continue;
}
}
Even after calling $doctrine->resetManager()
, the next $em
and $connection
seem to be in a “rollback only” state, and commit()
fails.
Environment:
- Symfony: 5.4.48
- Doctrine ORM: 2.20.3
- PHP: 7.4.30
- OS: Windows
What I’ve tried:
- Resetting the EntityManager with
$doctrine->resetManager()
- Reacquiring the EntityManager and Connection after rollback
- Checking transaction state with
$connection->isRollbackOnly()
Questions:
- Is this the expected behavior for Doctrine ORM?
- How can I fully reset the EntityManager/Connection so that the next transaction works?
- Is there a recommended pattern for batch processing with per-iteration transactions in Doctrine?