Details
-
Type:
Improvement
-
Status:
Open
-
Priority:
Major
-
Resolution: Unresolved
-
Affects Version/s: 2.0
-
Fix Version/s: None
-
Component/s: None
-
Security Level: All
-
Labels:None
Description
The problem is this:
$bar = new \entity\content\ContentTag();
$bar->setName('bar');
$em->persist($bar);
$existingTag = $em->getRepository('entity\content\ContentTag')->findOneByName('bar');
Seeing as in EntityRepository "find()" queries the Unit of Work first, and "findBy()" goes directly to the persister, only remotely stored objects will be found. Now if I want a tag object to attach related tags, it would have to query by name to see if an object already exist, BUT it wont find one as the UoW has not been committed, resulting in a new one being created, ultimately resulting in a PDO error on the unique name constraint.
This can be "solved" by inserting a flush, but it is impossible to know whether a flush is required, without knowledge of what comes next. I.e. for one part to know it has to flush, it has to know another wants to fetch an object you just created.
This causes an unacceptable amount of coupling.
Somehow the repo will have to be able execute DQL against the objects in the UoW. This does not have to be full support (straight away), but it should fail (throw an exception) if the possibility exists that the UoW contains items that are excluded (e.g. the operation is not supported and the UoW still contains items).
For right now, this means the EntityManager should throw an exception if DQL is executed on the type when the UoW is not empty. Until the time that the EntityManager can query the UoW using DQL. The alternative would be to "flush" before every operation that goes to the database for data.
Activity
| Field | Original Value | New Value |
|---|---|---|
| Fix Version/s | 2.0 [ 10021 ] |
| Affects Version/s | 2.0 [ 10021 ] | |
| Fix Version/s | 2.0 [ 10021 ] |
| Workflow | jira [ 11358 ] | jira-feedback [ 13851 ] |
| Workflow | jira-feedback [ 13851 ] | jira-feedback2 [ 15715 ] |
| Workflow | jira-feedback2 [ 15715 ] | jira-feedback3 [ 17972 ] |
- Request to http://www.doctrine-project.org/fisheye/ failed: Error in remote call to 'FishEye 0 (http://www.doctrine-project.org/fisheye/)' (http://www.doctrine-project.org/fisheye) [AbstractRestCommand{path='/rest-service-fe/search-v1/crossRepositoryQuery', params={query=DDC-586, expand=changesets[-21:-1].revisions[0:29],reviews}, methodType=GET}] : Received status code 503 (Service Temporarily Unavailable)
Hi,
you mention a good point, however, this currently only affects findBy queries made through a repository. A DQL query already triggers a flush when there are pending insertions but this still has its own problems. First of, querying against the objects in the UoW is not a viable solution in my eyes.
For a regular find() (by identifier) the situation is clear anyway, you must flush prior to a lookup on an entity you previously persisted in the same request because, by definition, generated primary key values are only guaranteed to be available after the next flush.
Automatic flushing if the UoW has pending inserts (new objects) and a query is executed (either through DQL or a repository) currently has its own set of problems, namely that it is still subject to infinite recursion if such a query is triggered in an event (listener) that executes during commit of a UoW, and secondly, that it will easily lead to double-flushes that cause unnecessary overhead (currently a flush() even if nothing needs to be done is not free because the UoW actually has to check whether nothing needs to be done). Both of these problems could be addressed with some sort of flags, but the question still is whether its not better to flush manually in the first place.
That would mean, in your example, you should flush after persisting the new objects, irrespectively of what code comes next, you persisted (a) new object(s) and you want to make sure these are fully available to the rest of the script.