[Docs] Explicit transaction example with connection does not close EntityManager at rollback #7207

Open
opened 2026-01-22 15:46:55 +01:00 by admin · 4 comments
Owner

Originally created by @ToshY on GitHub (Aug 5, 2023).

Bug Report

Q A
BC Break no
Version >=2.5.0

Summary

  • The first example for an explicit transaction (using the Doctrine\DBAL\Connection API) has lost the part that closes the EntityManager, therefore making it no longer "functionally equivalent" to the subsequent example using EntityManager#transactional($func).

Current behavior

<?php
// $em instanceof EntityManager
$em->getConnection()->beginTransaction(); // suspend auto-commit
try {
    //... do some work
    $user = new User;
    $user->setName('George');
    $em->persist($user);
    $em->flush();
    $em->getConnection()->commit();
} catch (Exception $e) {
    $em->getConnection()->rollback();
    throw $e;
}

Expected behavior

<?php
// $em instanceof EntityManager
$em->getConnection()->beginTransaction(); // suspend auto-commit
try {
    //... do some work
    $user = new User;
    $user->setName('George');
    $em->persist($user);
    $em->flush();
    $em->getConnection()->commit();
} catch (Exception $e) {
    $em->close();
    $em->getConnection()->rollback();
    throw $e;
}
Originally created by @ToshY on GitHub (Aug 5, 2023). ### Bug Report <!-- Fill in the relevant information below to help triage your issue. --> | Q | A |------------ | ------ | BC Break | no | Version | >=2.5.0 #### Summary * The first example for an [explicit transaction](https://github.com/doctrine/orm/blob/2.5/docs/en/reference/transactions-and-concurrency.rst#approach-2-explicitly) (using the `Doctrine\DBAL\Connection` API) has lost the part that closes the EntityManager, therefore making it no longer ["functionally equivalent"](https://github.com/doctrine/orm/blob/a616914887ea160db4158d2c67752e99624f7c8a/docs/en/reference/transactions-and-concurrency.rst?plain=1#L94) to the subsequent example using `EntityManager#transactional($func)`. #### Current behavior <!-- What is the current (buggy) behavior? --> ```php <?php // $em instanceof EntityManager $em->getConnection()->beginTransaction(); // suspend auto-commit try { //... do some work $user = new User; $user->setName('George'); $em->persist($user); $em->flush(); $em->getConnection()->commit(); } catch (Exception $e) { $em->getConnection()->rollback(); throw $e; } ``` #### Expected behavior <!-- What was the expected (correct) behavior? --> ```php <?php // $em instanceof EntityManager $em->getConnection()->beginTransaction(); // suspend auto-commit try { //... do some work $user = new User; $user->setName('George'); $em->persist($user); $em->flush(); $em->getConnection()->commit(); } catch (Exception $e) { $em->close(); $em->getConnection()->rollback(); throw $e; } ```
Author
Owner

@mpdude commented on GitHub (Aug 9, 2023):

What about this code?

597a63a86c/lib/Doctrine/ORM/UnitOfWork.php (L477-L487)

When an exception occurs inside UnitOfWork::commit(), the EM is closed before the exception is re-thrown. Isn't that what you're looking for?

@mpdude commented on GitHub (Aug 9, 2023): What about this code? https://github.com/doctrine/orm/blob/597a63a86ca8c5f9d1ec2dc74fe3d1269d43434a/lib/Doctrine/ORM/UnitOfWork.php#L477-L487 When an exception occurs inside `UnitOfWork::commit()`, the EM is closed before the exception is re-thrown. Isn't that what you're looking for?
Author
Owner

@ToshY commented on GitHub (Aug 9, 2023):

@mpdude I don't think we are on the same page.

As it's currently not "funcionally equivalent", I propose to update the documentation to include $em->close() in the catch block before the rollback, in order to be consistent with the behavior of EntityManager#transactional as mentioned in the text.

@ToshY commented on GitHub (Aug 9, 2023): @mpdude I don't think we are on the same page. * I have no issues with the code implementations, just the example in the documentations. I'm trying to point out that the example does not correspond to textual explanation that is provided. * Please not that it concerns an [**explicit transaction**](https://github.com/doctrine/orm/blob/2.5/docs/en/reference/transactions-and-concurrency.rst#approach-2-explicitly), so it uses `Doctrine\DBAL\Connection`. Looking at the [`Connection`](https://github.com/doctrine/dbal/blob/17d7baff12c60ebbb90420504ff63cefff8e021e/src/Connection.php#L1498C5-L1498C6) it only performs a rollback, and does not close the entitymanager unlike [`EntityManager#transactional($func)`](https://github.com/doctrine/orm/blob/19db7510a7b49605a9139fc2964342a98a682a8c/lib/Doctrine/ORM/EntityManager.php#L224), making the following sentence in the documentation incorrect: https://github.com/doctrine/orm/blob/19db7510a7b49605a9139fc2964342a98a682a8c/docs/en/reference/transactions-and-concurrency.rst?plain=1#L87-L88 As it's currently not "funcionally equivalent", I propose to update the documentation to include `$em->close()` in the catch block before the rollback, in order to be consistent with the behavior of `EntityManager#transactional` as mentioned in the text.
Author
Owner

@mpdude commented on GitHub (Aug 9, 2023):

Doesn't the UoW already close the entity manager when an exception is thrown from inside UoW::commit()?

@mpdude commented on GitHub (Aug 9, 2023): Doesn't the UoW already close the entity manager when an exception is thrown from inside `UoW::commit()`?
Author
Owner

@mpdude commented on GitHub (Aug 9, 2023):

What I want to say is:

From the user's perspective, you don't have to close the EntityManager, in neither of the two ways. The ORM code will make sure it will be closed.

@mpdude commented on GitHub (Aug 9, 2023): What I want to say is: From the user's perspective, you don't have to close the EntityManager, in neither of the two ways. The ORM code will make sure it will be closed.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#7207