[DDC-2411] Null values get reset when rehydrating an already managed entity Created: 23/Apr/13 Updated: 09/May/13
|Project:||Doctrine 2 - ORM|
|Reporter:||Simon Garner||Assignee:||Benjamin Eberlei|
1) You have an entity with a ManyToOne relation (and probably other kinds too, but this is all I have tested) to another entity which is nullable. For example, let's say you have a Book entity which has an "illustrator" field which refers to a Person entity, representing the person who illustrated the book. If the book is not illustrated then you set the field to null.
2) You fetch a Book (by ID) which has its illustrator set to a particular Person.
3) You set that Book's illustrator to null.
4) Without flushing, you fetch the Book again, using different criteria: for example, by title. Because entities are Identity Mapped, this will run a query but then locate the same instance in memory, and try to hydrate that instance with the old data it just fetched.
5) Any fields on the instance that have modified values retain their new values (for example, if we changed the illustrator to a different Person, this would be retained), BUT any fields on the instance which are null get overwritten with the old data (so if we previously set the illustrator to null, without flushing, it would now be reset to the Person value that it had before).
There seems to be a mistaken assumption here that null values are fields that have not been hydrated, when this is not necessarily the case. Is this the intended behaviour?
The code that causes this behaviour is here: https://github.com/doctrine/doctrine2/blob/e561f47cb2205565eb873f0643637477bfcfc2ff/lib/Doctrine/ORM/Internal/Hydration/ObjectHydrator.php#L471
If you are wondering why anybody would want to fetch the entity again in step 4, my use case for this is the Symfony Validator (but I presume there could be others).
If there are any unique constraints (Symfony ones, not Doctrine ones) on the entity, e.g. if we had a unique constraint on the Book title field, then when validating the Book the Symfony Validator would check if there are already any Book entities with the same title as the Book we're validating. It will find the Book that we are working with, and because entities are identity mapped, it will act upon the same instance, and the situation above occurs.
// Create some entities
$john = new Person();
$jane = new Person();
$joe = new Person();
$book = new Book();
// Now let's try modifying the book
$book = $bookRepository->find(123);
// make some changes
// now validate our changes with Symfony Validator
// what happened to our book??
|Comment by Fabio B. Silva [ 24/Apr/13 ]|
Could you please try to write a failing test case or paste your entities ?
|Comment by Benjamin Eberlei [ 09/May/13 ]|
Verified by code review that this issue exists, but it will be very tricky to fix, because the null check is there for other reasons as well.