DDC-2757: Manual transcation handling not possible when transaction fails, documentation gives wrong example #3452

Closed
opened 2026-01-22 14:20:07 +01:00 by admin · 4 comments
Owner

Originally created by @doctrinebot on GitHub (Oct 23, 2013).

Originally assigned to: @beberlei on GitHub.

Jira issue originally created by user baldman:

The current version of documentation states in section:

13.1.2. Approach 2: Explicitly

that one can use a custom transaction handling. One of the described things is that one has a responsibility for closing the entity manager, after exception is thrown.

However, the fact is that the unit of work will close itself regardless, so closing the EM is not up to the user (documentation is wrong there). In fact, there is no way, one can say: Don't close the entity manager, I know what I am doing, just clear the thing and let me continue somehow (which is another topic/feature).

What is an issue however is that once you reset an entity manager/obtain a new one, the old objects fetched are not usable, even though one just needs some information from them (for example, their primary keys) so that a new object can be created. When I try using them, there is a PHP Notice that spl_object_hash of the given object cannot be found inside entityIdentifiers (line 2852, UnitOfWork.php), and merging previously selected entities into the new entity manager does not work for some reason -- the entity stays in detached state. So the only possibility is to refetch all data. Which means, scenarios such as these:

foreach ($data as $record) {
    // update the entity
    // persisting new $record fails, as some constraint gets violated (unique, for instance)
    // catch the exception, obtain new EM, continue
}

... won't work, or all highly problematic to say the least. I am not able to figure out, how to handle such scenarios properly using Doctrine. Just to make the scenario clear, there is no way I can check beforehand, that given constraint will be violated, short of complete exclusive table lock.

Originally created by @doctrinebot on GitHub (Oct 23, 2013). Originally assigned to: @beberlei on GitHub. Jira issue originally created by user baldman: The current version of documentation states in section: **13.1.2. Approach 2: Explicitly** that one can use a custom transaction handling. One of the described things is that one has a responsibility for closing the entity manager, after exception is thrown. However, the fact is that the unit of work will close itself regardless, so closing the EM is not up to the user (documentation is wrong there). In fact, there is no way, one can say: Don't close the entity manager, I know what I am doing, just clear the thing and let me continue somehow (which is another topic/feature). What is an issue however is that once you reset an entity manager/obtain a new one, the old objects fetched are not usable, even though one just needs some information from them (for example, their primary keys) so that a new object can be created. When I try using them, there is a _PHP Notice_ that spl_object_hash of the given object cannot be found inside entityIdentifiers (line 2852, UnitOfWork.php), and merging previously selected entities into the new entity manager does not work for some reason -- the entity stays in detached state. So the only possibility is to refetch all data. Which means, scenarios such as these: ``` foreach ($data as $record) { // update the entity // persisting new $record fails, as some constraint gets violated (unique, for instance) // catch the exception, obtain new EM, continue } ``` ... won't work, or all highly problematic to say the least. I am not able to figure out, how to handle such scenarios properly using Doctrine. Just to make the scenario clear, there is no way I can check beforehand, that given constraint will be violated, short of complete exclusive table lock.
admin added the Bug label 2026-01-22 14:20:07 +01:00
admin closed this issue 2026-01-22 14:20:07 +01:00
Author
Owner

@doctrinebot commented on GitHub (Oct 26, 2013):

Comment created by @beberlei:

Yes, if a constraint fails it is usually necessary to start all over. However it should be possible for you to check for NULL, unique key or foreign key constraints in your code before calling flush.

@doctrinebot commented on GitHub (Oct 26, 2013): Comment created by @beberlei: Yes, if a constraint fails it is usually necessary to start all over. However it should be possible for you to check for NULL, unique key or foreign key constraints in your code before calling flush.
Author
Owner

@doctrinebot commented on GitHub (Oct 26, 2013):

Comment created by @beberlei:

I updated the documentation accordingly, as this is a documentation error.

@doctrinebot commented on GitHub (Oct 26, 2013): Comment created by @beberlei: I updated the documentation accordingly, as this is a documentation error.
Author
Owner

@doctrinebot commented on GitHub (Oct 26, 2013):

Issue was closed with resolution "Fixed"

@doctrinebot commented on GitHub (Oct 26, 2013): Issue was closed with resolution "Fixed"
Author
Owner

@doctrinebot commented on GitHub (Oct 29, 2013):

Comment created by baldman:

Okay, just wanted to point out that checking for constraints beforehand may not be possible. When at least two concurrent clients try to insert the same thing with the same unique constraint for example, there is nothing one can do to check for the constraint short of pessimistic lock on the table (because one process may insert conflicting data in between the check and the flush), which is not feasible in all scenarios. What I was trying to look up in the documentation was a way around this. And interestingly, obtaining new EM and merging entities (existing ones, fetched from database and not modified at all) back into it resulted in problems as well (the mentioned NOTICE problem).

@doctrinebot commented on GitHub (Oct 29, 2013): Comment created by baldman: Okay, just wanted to point out that checking for constraints beforehand may not be possible. When at least two concurrent clients try to insert the same thing with the same unique constraint for example, there is nothing one can do to check for the constraint short of pessimistic lock on the table (because one process may insert conflicting data in between the check and the flush), which is not feasible in all scenarios. What I was trying to look up in the documentation was a way around this. And interestingly, obtaining new EM and merging entities (existing ones, fetched from database and not modified at all) back into it resulted in problems as well (the mentioned NOTICE problem).
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: doctrine/archived-orm#3452