[DDC-3696] flushing traversable objects Created: 17/Apr/15  Updated: 18/Apr/15

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.5, 2.5.1
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Major
Reporter: mw Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm, unitofwork


 Description   

Hi,

https://github.com/doctrine/doctrine2/blob/master/lib/Doctrine/ORM/UnitOfWork.php#L331

it would be easier if you could the method "flush" pass a traversable object. I've implement this behavior in my decorated entity manager. In my opinion this should be an official supported behavior.

The new code should be inside of Orm\UnitOfWork::commit($entity = null) and looks like the following code:

// Compute changes done since last commit.
if( $entity instanceof \Traversable ) {
	$entity = iterator_to_array( $entity );
}

By the way, the foreach part can be simplified to one line. This can be made possible by array_walk.
You can use:

} elseif (is_array($entity)) {
	array_walk($entity, array($this, 'computeSingleEntityChangeSet'));
}

Now, the new code in one piece:

// Compute changes done since last commit.
if( $entity instanceof \Traversable ) {
	$entity = iterator_to_array( $entity );
}

if ($entity === null) {
	$this->computeChangeSets();
} elseif (is_object($entity)) {
	$this->computeSingleEntityChangeSet($entity);
} elseif (is_array($entity)) {
	array_walk($entity, array($this, 'computeSingleEntityChangeSet'));
}

Thanks in advance.



 Comments   
Comment by Marco Pivetta [ 17/Apr/15 ]

Two things:

1) we are more inclined to remove the parameter from flush(), as it was exploited for purposes it wasn't designed for.
2) what happens if you persist an entity that is a traversable?

Comment by mw [ 17/Apr/15 ]

1.Is that really planned? I guess this is a helpful feature and makes not a difference if you flush a small collection of entities before you flush the remaining entities without the parameter.

2. The object will be treated as entity, because it's an object. This will throw an "Doctrine\ORM\Mapping\MappingException" exception with following message:

Class "SplObjectStorage" is not a valid entity or mapped super class.
Exception-Class: Doctrine\ORM\Mapping\MappingException 
Exception-Code: 0 
Exception-File: Composer/doctrine/orm/lib/Doctrine/ORM/Mapping/MappingException.php 
Exception-Line: 346

This simple senseless code shows you what you can do to test this behavior.

$em = Doctrine_Factory::getEntityManager();
$em->persist($entity);
$x = new SplObjectStorage();
$x->attach($entity);
$em->flush($x);
Comment by Marco Pivetta [ 17/Apr/15 ]

You can implement the Traversable interface (as iterator or iteratoraggregate) on any entity.

As for "planned", it obviously won't happen in 2.x.

We are mainly interested in finding better ways to speed up flush() operations rather than delegating transactional boundaries knowledge to the user.

Anyway, so far, flush($entities) has been more of a source of bugs rather than an actual useful API.

Comment by mw [ 18/Apr/15 ]

The Traversable interface serves to detect whether a class is traversable using foreach. The flush parameter surrenders this parameter one-to-one to $this->unitOfWork->commit($entity).
What I want to do is to hand over an traversable object to the method EntityManager::flush with a collection of entities instead of an single entity object. It's also possible to pass a collection of entities as array. But it's not possible to pass a collection of entities as an object, because when passing an object UnitOfWork::commit assumes that it's an entity. To implement the Traversable interface on any entity will not help and is not the same intention. Because an Traversable object it means, that is a collection of entities like an array.

In my opinion there are not objections that speak against it to support traversable object (SplObjectStorage, ArrayIterator, ArrayObject).

There are two ways to do that.

The first option would be:

// Compute changes done since last commit.
if( $entity instanceof \Traversable ) {
	$entity = iterator_to_array( $entity );
}

if ($entity === null) {
	$this->computeChangeSets();
} elseif (is_object($entity)) {
	$this->computeSingleEntityChangeSet($entity);
} elseif (is_array($entity)) {
	array_walk($entity, array($this, 'computeSingleEntityChangeSet'));
}

The second option would be:

// Compute changes done since last commit.
if ($entity === null) {
	$this->computeChangeSets();
} elseif (is_array($entity) || $entity instanceof \Traversable) {
	foreach ($entity as $object) {
		$this->computeSingleEntityChangeSet($object);
	}
} elseif (is_object($entity)) {
	$this->computeSingleEntityChangeSet($entity);
}

By the way: the SplObjectStorage object has the benefit that every entity is present only once.





[DDC-3681] [GH-1378] Feature to force-increment entity version Created: 09/Apr/15  Updated: 10/Apr/15

Status: Awaiting Feedback
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers, ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: New Feature Priority: Minor
Reporter: Doctrine Bot Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: persister, unitofwork, versioned

Issue Links:
Dependency
depends on DDC-3683 [GH-1380] Fix issue with second-level... Open
Duplicate
is duplicated by DDC-3640 Force version increment via mapped pr... Resolved

 Description   

This issue is created automatically through a Github pull request on behalf of DHager:

Url: https://github.com/doctrine/doctrine2/pull/1378

Message:

Submitting for feedback and experimentation.

The major use-case for this involves using certain entities as the versioned-gatekeepers for changes that don't directly live on the same entity. For example, using the version of a `PurchaseOrder` to control changes to any of its child `PurchaseOrderLineItem` objects.






[DDC-3674] Additional informations when closing EntityManager Created: 08/Apr/15  Updated: 08/Apr/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Daniel Mecke Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: orm, unitofwork


 Description   

When the EntityManager is closed there is no way to find out why it has been closed afterwards. For example it would be nice if ORMException::entityManagerClosed() could add the information which query caused it to close. That would ease debugging a lot.
Maybe the EntityManager::close() method could get a parameter which stores the query or informations about it in a property next to the EntityManager::closed property?






[DDC-3624] [GH-1338] [DDC-3619] Update identityMap when entity gets managed again Created: 17/Mar/15  Updated: 17/Mar/15  Resolved: 17/Mar/15

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.7
Fix Version/s: 2.5, 2.4.8
Security Level: All

Type: Bug Priority: Major
Reporter: Doctrine Bot Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: garbage-collection, identity-map, object-hash, persist, remove, unitofwork

Issue Links:
Dependency
is required for DDC-3619 spl_object_hash collision Resolved
Reference
relates to DDC-3619 spl_object_hash collision Resolved

 Description   

This issue is created automatically through a Github pull request on behalf of nclavaud:

Url: https://github.com/doctrine/doctrine2/pull/1338

Message:

http://www.doctrine-project.org/jira/browse/DDC-3619

When using SoftDeleteable doctrine extension, an entity can be scheduled
for deletion, then persisted before flushing. In such a case, the entity
was removed from the unit of work identity map and no reference was
hold. This could lead to spl_object_hash collisions, and prevent
another, new entity to be persisted later.

This fix makes sure the unit of work identity map holds a reference to
the entity after it has been soft-deleted.



 Comments   
Comment by Doctrine Bot [ 17/Mar/15 ]

A related Github Pull-Request [GH-1338] was assigned:
https://github.com/doctrine/doctrine2/pull/1338

Comment by Doctrine Bot [ 17/Mar/15 ]

A related Github Pull-Request [GH-1338] was labeled:
https://github.com/doctrine/doctrine2/pull/1338

Comment by Doctrine Bot [ 17/Mar/15 ]

A related Github Pull-Request [GH-1338] was closed:
https://github.com/doctrine/doctrine2/pull/1338





[DDC-3619] spl_object_hash collision Created: 17/Mar/15  Updated: 17/Mar/15  Resolved: 17/Mar/15

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.7
Fix Version/s: 2.5, 2.4.8
Security Level: All

Type: Bug Priority: Major
Reporter: Aleksandr Khristenko Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: garbage-collection, identity-map, object-hash, persist, remove, unitofwork

Attachments: File DDC3619Test.php    
Issue Links:
Dependency
depends on DDC-3624 [GH-1338] [DDC-3619] Update identityM... Resolved
Reference
is referenced by DDC-3624 [GH-1338] [DDC-3619] Update identityM... Resolved

 Description   

The code below demonstrate problem.

$user = $entityManager->find(User::class, $id); // get entity from db
$entityManager->remove($user); // remove user
$entityManager->persist($user); // cancel remove
unset($user);
/* at this moment spl_object_hash($user) is presented in the UoW, but the $user isn't presented in the identity map in UoW */
$user2 = new User(); // spl_object_hash($user2) may be equal to spl_object_hash($user) because $user has no reference
$entityManager->persist($user2);
$entityManager->flush(); //$user2 will not be saved, because UoW think, that is already exists


 Comments   
Comment by Marco Pivetta [ 17/Mar/15 ]

spl_object_hash($user2) may be equal to spl_object_hash($user) because $user has no reference

this seems wrong, since $user won't get garbage collected

Comment by Aleksandr Khristenko [ 17/Mar/15 ]

Why? The $user has no reference to it, so it may be collected.
I use SoftDeleteabale extension and faced with this problem.
My code is look like:

function delete($id) {
  $entity = $entityManager->find(Entity::class, $id);
  $entityManager->delete($entity); // the softdeleteable extension call persist($entity) and remove $entity from sheduledForDeletion in onFlush
  $entityManager->flush($entity);
} // after this function the UoW contains spl_object_hash($entity), but not contains $entity. After leave function $entity collected.
function createAnother() {
  $anotherEntity = new AnotherEntity();
  $entityManager->persist($anotherEntity);
  $entityManager->flush($anotherEntity); // there is a spl_object_hash collision and the entity is not saved
}
function main() {
  //...
  delete($id);
  //...
  createAnother();
}
Comment by Marco Pivetta [ 17/Mar/15 ]

Aleksandr Khristenko the UoW has an internal reference to $user, so it cannot be garbage collected

Comment by Marco Pivetta [ 17/Mar/15 ]

I suggest abstracting this problem into a test case in order to remove these doubts upfront.

Comment by Aleksandr Khristenko [ 17/Mar/15 ]

Aleksandr Khristenko the UoW has an internal reference to $user, so it cannot be garbage collected

Yes, but when we call remove($entity) this internal reference move from identityMap to entityDeletions array. And when we after that call persist($entity) this internal reference remove from entityDeletions array but NOT added to identityMap. So, after that UoW has not an internal reference to $user.

Comment by Aleksandr Khristenko [ 17/Mar/15 ]

I attached the test, which demonstrates that reference to entity from UoW is lost.

Comment by Nicolas [ 17/Mar/15 ]

I am also using SoftDeleteable Doctrine extension (https://github.com/Atlantic18/DoctrineExtensions) and facing a similar issue.

My scenario is:

  • fetch 2 entities from db ;
  • soft-delete these 2 entities (then flush) ;
  • create 3 new entities and persist them (then flush).

Problem is: 1 of the 3 entities won't be persisted (same $oid than one of the soft-deleted ones).

I've created a PR here that solves my issue:
https://github.com/doctrine/doctrine2/pull/1338

Does it make sense to you?

Comment by Doctrine Bot [ 17/Mar/15 ]

A related Github Pull-Request [GH-1338] was closed:
https://github.com/doctrine/doctrine2/pull/1338





[DDC-3524] [GH-1272] [DDC-2704] - merge inherited transient properties - merge properties into uninitialized proxies Created: 20/Jan/15  Updated: 25/Jan/15  Resolved: 25/Jan/15

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master, 2.4.7
Fix Version/s: 2.5
Security Level: All

Type: Bug Priority: Major
Reporter: Doctrine Bot Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: inheritance, merge, private-properties, transient-properties, unitofwork

Issue Links:
Dependency
is required for DDC-2704 When using Discriminator EntityManage... Resolved

 Description   

This issue is created automatically through a Github pull request on behalf of Ocramius:

Url: https://github.com/doctrine/doctrine2/pull/1272

Message:

See http://www.doctrine-project.org/jira/browse/DDC-2704 - DDC-2704



 Comments   
Comment by Doctrine Bot [ 24/Jan/15 ]

A related Github Pull-Request [GH-1272] was unlabeled:
https://github.com/doctrine/doctrine2/pull/1272

Comment by Doctrine Bot [ 25/Jan/15 ]

A related Github Pull-Request [GH-1272] was merged:
https://github.com/doctrine/doctrine2/pull/1272





[DDC-3375] UnitOfWork: new operation attach(): merge without persist Created: 06/Nov/14  Updated: 08/Nov/14  Resolved: 07/Nov/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Mathieu De Zutter Assignee: Marco Pivetta
Resolution: Won't Fix Votes: 0
Labels: unitofwork


 Description   

Currently UnitOfWork provides the following three methods that make entities cross the boundaries of being managed or not:

  • persist()
  • merge()
  • detach()

In my opinion, there's an operation missing: attach(). It would be similar to merge(), but it would not call persist(). It would be the counterpart of detach().

Example 1: Simple case

if (...)
$person = new Person;
else
$person = $em->find('Person', $id);

// At some point I decide that I don't want to store the person, so I don't call persist()

$dog = new Dog;
$em->persist($dog);

$em->flush(); // OK, commits only the dog

Example 2: Same, but the person is serialized along the way

if (...)
$person = new Person;
else
$person = $em->find('Person', $id);

// Serialize the person
$serializedPerson = serialize($person);

// At some point I want to restore the person
$person = unserialize($serializedPerson);

// Because it could have been a managed entity before, I need to merge it.
$person = $em->merge($person);

// But yet again, I decide that I don't want to store the person, so I don't call persist()

$dog = new Dog;
$em->persist($dog);

$em->flush(); // Oops, if the person was NEW, it has become managed, so it is commited now!

If merge() was replaced by attach(), flush() would not have commited the person.



 Comments   
Comment by Christophe Coevoet [ 06/Nov/14 ]

I don't understand what attach would do in your case. flush is about flushing the whole unit of work. I don't understand what attach() would do if it does not attach the entity to the unit of work.

Comment by Christophe Coevoet [ 06/Nov/14 ]

And actually, the opposite of detach() already exists: it is persist(). It makes the object enter the unit of work, while detach makes it leave the unit of work.

Note that merge is not making the object cross the boundary. The object passed to merge() never enters the unit of work. what happens is that the data inside this object are applied to an object inside the boundary (potentially a new one if there was no object with this identifier).
When using merge, you are explicitly asking to apply the data inside the unit of work, so it is logical that something gets flushed.

and note that in your example 1, your person is managed half of the time (when coming from find() rather than a new instance). And in such case, it will be flushed. You are not flushing only the dog.

Comment by Mathieu De Zutter [ 08/Nov/14 ]

OK, makes sense.





[DDC-3370] [GH-1173] Fix merging of entities with associations to identical entities. Created: 05/Nov/14  Updated: 11/Nov/14  Resolved: 11/Nov/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.5, 2.4.6
Fix Version/s: 2.5
Security Level: All

Type: Bug Priority: Major
Reporter: Doctrine Bot Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: cascade, merge, unitofwork


 Description   

This issue is created automatically through a Github pull request on behalf of mathieudz:

Url: https://github.com/doctrine/doctrine2/pull/1173

Message:

Without this patch, when an entity that refers multiple times to the same
associated entity gets merged, the second references becomes null.

The main issue is that even though doMerge returns a managed copy, that value
is not used while cascading the merge. These identicial entities are already
detected through the visitor map, but they are ignored. There should be some
refactoring so cascadeMerge calls a function that checks if the parent must be
updated, based on the return value of its call to doMerge. However, this patch
tries to impact the code as little as possible, and only introduces a new
function to avoid duplicate code.

The secondary issue arises when using inverted associations. In that case, it
is possible that an entity to be merged is already merged, so the the visitor
map is looked up by the hash of a managed copy instead of the original entity.
This means that in this case the visitor map entries should also be set to the
entity, instead of being set to 'true'.



 Comments   
Comment by Doctrine Bot [ 11/Nov/14 ]

A related Github Pull-Request [GH-1173] was assigned:
https://github.com/doctrine/doctrine2/pull/1173

Comment by Doctrine Bot [ 11/Nov/14 ]

A related Github Pull-Request [GH-1173] was closed:
https://github.com/doctrine/doctrine2/pull/1173





[DDC-3318] [GH-1143] Fixed a bug so that a versioned entity with a oneToOne id can be created Created: 23/Sep/14  Updated: 19/Oct/14  Resolved: 19/Oct/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.6
Fix Version/s: 2.5
Security Level: All

Type: Bug Priority: Major
Reporter: Doctrine Bot Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: hydration, hydrator, onetoone, unitofwork, versioned


 Description   

This issue is created automatically through a Github pull request on behalf of MajorCaiger:

Url: https://github.com/doctrine/doctrine2/pull/1143

Message:

  • Fixed the basic entity persister so that versioned OneToOne entities can be created
  • Created an IdentifierConverter utility class
  • Moved the logic for the flatten identifier method into the new utility class
  • Replaced calls for private flattenIdentifier to use new utility
  • Added appropriate unit tests


 Comments   
Comment by Doctrine Bot [ 19/Oct/14 ]

A related Github Pull-Request [GH-1143] was closed:
https://github.com/doctrine/doctrine2/pull/1143





Regression in reComputeSingleEntityChangeset (DDC-3160)

[DDC-3208] Merge DDC-3160 back into 2.4.x Created: 06/Jul/14  Updated: 11/Jul/14  Due: 11/Jul/14  Resolved: 11/Jul/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.3
Fix Version/s: 2.4.4
Security Level: All

Type: Sub-task Priority: Blocker
Reporter: Marco Pivetta Assignee: Marco Pivetta
Resolution: Fixed Votes: 3
Labels: changeset, listener, unitofwork

Issue Links:
Reference
is referenced by DDC-2996 UnitOfWork::recomputeSingleEntityChan... Resolved

 Description   

DDC-3160 should be backported to 2.4.4 once user feedback is collected.



 Comments   
Comment by Kevin Bond [ 06/Jul/14 ]

I ran the DoctrineExtensions test suite with ORM 2.4 with this fix and it passed.

Comment by Justin Zimmerman [ 06/Jul/14 ]

For the project I was working on where I started having issues with the 2.4.3 update and Atlantic18/DoctrineExtensions, the DDC-3160 solution did fix the problems that I was seeing. Granted, I am only using the Tree portion of that library, I cannot say anything about the other parts of it.

I just ran a test with the latest DoctrineExtensions code. These are the results I get with running Doctrine 2.4.3:

FAILURES!
Tests: 411, Assertions: 1760, Errors: 71, Skipped: 62.

When I patch up the Doctrine 2.4.3 branch with the DDC-3160 fix, I get much better results:

OK, but incomplete, skipped, or risky tests!
Tests: 411, Assertions: 2410, Skipped: 62.

From what I can tell, this does seem to fix the DoctrineExtensions issues which I believe was eventually tracked down to being caused by the DDC-2996 fix.

Comment by Eric Coleman [ 08/Jul/14 ]

Patch is working for us.

Comment by Marco Pivetta [ 10/Jul/14 ]

Going to merge this back into 2.4.x asap

Comment by Marco Pivetta [ 11/Jul/14 ]

Merged at https://github.com/doctrine/doctrine2/commit/5c5abb6771c1f5ab8318f76aed79ce1da8a0300d





[DDC-3179] Non initialized Proxy object with post remove listener Created: 19/Jun/14  Updated: 26/Jun/14  Resolved: 26/Jun/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Geoffrey Brier Assignee: Marco Pivetta
Resolution: Won't Fix Votes: 0
Labels: proxy, unitofwork

Issue Links:
Dependency
is required for DDC-3180 [GH-1065] [DDC-3179] EntityNotFoundEx... Resolved

 Description   

Hi,

My use case is as follow:
I have an object "Demand" linked to a "Guarantor" which possesses a few files to delete from the server on the "post remove" doctrine event. The Demand -> Guarantor relation is configured to cascade persist and remove on the ORM side.

We intended to remove a "Demand" object but were getting an "EntityNotFoundException". After debugging a bit with a friend (eric geloen) we realized that when non initialized proxies have a listener on the post remove event, the object cannot loads itself as it does not exist anymore and this throws an exception. In my case, this means that I cannot delete the "Guarantor's" files.

So I was wondering if it was a bug coming from doctrine or a normal behavior. One could consider that it is our responsibility to correctly load an object and its graph yet one could also consider that this is a limitation (not to initialize the proxies beforehand).

While testing we moved the following snippet (that was in the cascadeRemove method) in the "executeDeletions" method right before the delete call and it was working.

if ($entity instanceof Proxy && !$entity->__isInitialized__) {
    $entity->__load();
}

What is your opinion?



 Comments   
Comment by Marco Pivetta [ 19/Jun/14 ]

Geoffrey Brier this may be a bug, but it needs a test case reproducing your exact scenario.

It would also be interesting to look at what you have so far.

Also, lowering priority.

Comment by Marco Pivetta [ 26/Jun/14 ]

Resolution in DDC-3180





[DDC-3101] Calling computeChangeSet twice generates invalid changeSet Created: 28/Apr/14  Updated: 29/Apr/14  Resolved: 29/Apr/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4.2
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Minor
Reporter: Filip Procházka Assignee: Benjamin Eberlei
Resolution: Invalid Votes: 0
Labels: unitofwork


 Description   

Let's say I have an entity Answer and Question, the Question has two relations lastPost and solution. I also have a listener on preFlush for the Answer entity.

When the entity is changed (or created), the listener is called and it finds lastPost and fills the relation in Question. The change was never persisted, so I've added $UoW->computeChangeSet() at the end of the listener over the changed Question instance. The documentation mentions it at onFlush event http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/events.html#preflush, but I figured it's probably the only way.

So there we go, I have working form that I submit and the relation lastPost is always updated and propagated to database as expected.

Now comes the problem.

When I change the solution relation and the lastPost is updated from listener, the changeSet that was prepared is overriden and becase the computeChangeSet method overwrites the original UoW::$originalEntityData, the new computed changeSet is wrong and contains only the new lastPost and the changes made before last call to computeChangeSet are lost (they will not be saved to database).

This is obviousely wrong and can be fixed either by not overwriting the originalEntityData property or by appending to changeSet (by fixing condition here https://github.com/doctrine/doctrine2/blob/35c8cd7f237a9a114303d14d573a28fb7d91b35e/lib/Doctrine/ORM/UnitOfWork.php#L624-L626 )

Edit:
I just figured it can be solved by using onFlush and recomputeSingleEntityChangeSet, but I really like the EntityListeners and they obviousely are not called on onFlush event.



 Comments   
Comment by Filip Procházka [ 29/Apr/14 ]

I still think this should be also doable in entity listener, but the bug appeared mostly becase of my bad usage...





[DDC-2704] When using Discriminator EntityManager#merge fails Created: 25/Sep/13  Updated: 25/Jan/15  Resolved: 25/Jan/15

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.4, 2.4.2
Fix Version/s: 2.5
Security Level: All

Type: Bug Priority: Major
Reporter: Vladyslav Petrovych Assignee: Marco Pivetta
Resolution: Fixed Votes: 2
Labels: inheritance, merge, private-properties, transient-properties, unitofwork

Issue Links:
Dependency
depends on DDC-3524 [GH-1272] [DDC-2704] - merge inherite... Resolved

 Description   

I have the following hierarchy:

  • AgentConfig has relation ManyToOne with AgentTask.
  • AgentTask has DiscriminatorColumn & DiscriminatorMap assigned to it.
  • AgentTask has relation ManyToOne with AgentTaskConfig.

I believe the problem is because of the following:

UnitOfWork#doMerge has the tries to get properties the following way:

// Merge state of $entity into existing (managed) entity
foreach ($class->reflClass->getProperties() as $prop) {

This obviously doesn't get the parent class (AgentTask) properties.

Later on UnitOfWork fails on line:

$prevClass->reflFields[$assocField]->getValue($prevManagedCopy)->add($managedCopy);

because $prevManagedCopy doesn't have properties set from entity.

My proposal is to get the properties the following way:

$properties = $class->reflClass->getProperties();
$parent = $class->reflClass;
while (($parent = $parent->getParentClass()) != null) {
    $properties = array_merge($parent->getProperties(), $properties);
}

// Merge state of $entity into existing (managed) entity
foreach ($properties as $prop) {


 Comments   
Comment by Rasmus Jensen [ 20/Jan/15 ]

I have this problem as well in .
The Merge operation does not copy properties of any parent class to the managed copy. My workaround when merging entities with inheritance is:
1. Receive detached entity that is instance of a subclass.
2. fetch a managed copy of the entity from database with id of detached entity.
3. manually set properties on the managed entity.
4. flush to save changes.

This is obviously only manageable with a relatively simple datastructure, and quickly becomes very messy with more complex entities and relationship hierarchies.

Would really appreciate a fix for this

Comment by Marco Pivetta [ 20/Jan/15 ]

A temporary workaround is to change properties into protected. I'll mark this for 2.5 and see if it can be fixed by then.

Comment by Marco Pivetta [ 25/Jan/15 ]

Handled in DDC-3524





[DDC-2496] Unexpected behaviour flushing single entity Created: 10/Jun/13  Updated: 17/Jun/13  Resolved: 12/Jun/13

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.4
Fix Version/s: None
Security Level: All

Type: Bug Priority: Major
Reporter: Hernan Rajchert Assignee: Marco Pivetta
Resolution: Invalid Votes: 0
Labels: orm, unitofwork


 Description   

The following works as expected:
$existingElement = $repository->find(1);
$existingElement->setSomething('foo');
$newElement = new Element('bar');
$em->persist($newElement);
$em->flush($newElement);
// The new element is added and the existing is not modified

The following does not:
$existingElement = $repository->find(1);
$em->remove(existingElement);
$newElement = new Element('bar');
$em->persist($newElement);
$em->flush($newElement);
// The new element is added and the existing is deleted (i didnt flush THAT element)

The following does not:
$newElement2 = new Element('foo');
$em->persist($newElement2);
$newElement = new Element('bar');
$em->persist($newElement);
$em->flush($newElement);
// Both elements are persisted, even if I only flushed $newElement



 Comments   
Comment by Hernan Rajchert [ 12/Jun/13 ]

By the way, I noticed in the code that this seems to be "expected behaviour", but it doesn't make too much sense, as the idea is to not disturb the original unit of work.

The problem arises when I call some findOrCreate methods that I've done. The idea is that those entities should be there, but not always are, and they usually occur on the middle of some other processing, so if I have some new elements before calling the findOrCreate I dont want them to be inserted until I flush them in particular.

Right now Im creating a new EntityManager (which involves a new connection), doing the insert there and then merging into the other EntityManager, but the merge is very error prone to the order you merge stuff.

Comment by Marco Pivetta [ 12/Jun/13 ]

Flushing with a given parameter is only about optimizing changeset computation - it is not meant to flush only the new element.

Comment by Hernan Rajchert [ 17/Jun/13 ]

So how would you recommend to resolve the findOrCreate issues?

Comment by Marco Pivetta [ 17/Jun/13 ]

You would have to flush afterwards.





[DDC-2338] Entity with composite foreign keys identifiers should be persisted after related entities without exception Created: 07/Mar/13  Updated: 12/Nov/14  Resolved: 12/Nov/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Minor
Reporter: Alessandro Tagliapietra Assignee: Marco Pivetta
Resolution: Can't Fix Votes: 0
Labels: autoincrement, commitorder, identifier, identity, orm, sequence, unitofwork
Environment:

Mac OSX 10.8, php 5.4.11, doctrine git master version


Issue Links:
Dependency
depends on DDC-2339 [GH-605] DDC-2338 Added failing test ... Resolved
Reference
relates to DDC-3389 [GH-1184] Postgres SERIAL is not a po... Resolved

 Description   

I've seen that when you create an entity with a composite foreign key as identifier it cannot be flushed until the related entities are already flushed to the database and not just persisted.

It would be nice to let the user flush all the entities together and just INSERT first the related entities to get the ID and then use that to INSERT the entity with composite foreign keys.

I'm going to create a pull request with the failing test.



 Comments   
Comment by Alessandro Tagliapietra [ 07/Mar/13 ]

Created pull request https://github.com/doctrine/doctrine2/pull/605

Comment by Doctrine Bot [ 12/Nov/14 ]

A related Github Pull-Request [GH-605] was closed:
https://github.com/doctrine/doctrine2/pull/605

Comment by Marco Pivetta [ 12/Nov/14 ]

Known limitation affecting only post-insert ID generation (mysql et simila)





[DDC-2317] [UnitOfWork] Entity in identityMap but not present in entityIdentifiers Created: 24/Feb/13  Updated: 26/Feb/13  Resolved: 26/Feb/13

Status: Closed
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3.2
Fix Version/s: None

Type: Bug Priority: Major
Reporter: Rémi Piotaix Assignee: Marco Pivetta
Resolution: Invalid Votes: 0
Labels: orm, unitofwork
Environment:

php 5.4.11, MySQL 5.5, ubuntu 12.10


Attachments: File Buff.php     File Competence.php     File CompetenceAction.php     File CompetenceActionBuff.php     File CompetenceActionBuffType.php    

 Description   

I'm using symfony 2.1.8 and sonata/admin-bundle
I have a quite complex entity mapping.

  • A Competence has many CompetenceAction (superclass)
  • CompetenceActionBuff is a subclass of CompetenceAction and has exactly one buff (selectable in the form by an 'entity' field).

When i want to edit a Competence, i have the following error message about the Buff entity linked to the CompetenceActionBuff:
"Entities passed to the choice field must be managed. [...]"
The exception is raised in Symfony/Bridge/Doctrine/Form/ChoiceList/EntityChoiceList.php at line 412

I've added some debug code in the EntityManager::contains() method and it shows that my entity is in the entityMap but his oid is not in the keys of entityIdentifiers making the call to UnitOfWork::isInIdentityMap() return false at line 1505.

When submitting the form, there is no problems. All the entities are correctly created in the database. The exception is thrown only when i want to edit the Competence object. Saying that the Buff object is not managed when it was first loaded from the database... strange, no?

Finally, i tried to comment the test

if (!$this->em->contains($entity)))

in EntityChoiceList::getIdentifierValues() and everything seemed to work properly.



 Comments   
Comment by Marco Pivetta [ 24/Feb/13 ]

Can you please reproduce this in an insulated environment (without symfony forms involved)?

Comment by Rémi Piotaix [ 24/Feb/13 ]

By doing this, all work properly, the exception is not thrown:

$competence = $this->getRepo(\Sistearth\JeuBundle\Entity\Competence\Competence::REPO)->find(1);
$buff = $competence->getActions()[0]->getBuff();
      
$em = $this->getDoctrine()->getEntityManager();
        
if(!$em->contains($buff))
    throw new \Exception("Not in EntityManager");

but if i add this after:

$form = $this->createForm(new \Sistearth\JeuBundle\Form\Competence\CompetenceType(), $competence);

then, the exception "Entities passed to the choice field must be managed. Maybe persist them in the entity manager?" is back.

I'll try to do some others tests...

Comment by Marco Pivetta [ 24/Feb/13 ]

Rémi Piotaix the problem is exactly the last bit Doctrine has no forms, so you will have to create a small script that reproduces the problem without symfony, starting from:

php composer.phar require doctrine/orm:dev-master@dev
Comment by Rémi Piotaix [ 24/Feb/13 ]

Bug found!

In the form type CompetenceActionBuffType, i marked the field buff with

array('by_reference"=>false)

. If by_reference is set to false, the modelData is cloned (here the Buff proxy) at line 349 in Form.php.
And, by cloning the object, the spl_object_hash of the clone is different from the original one's.

Is this a symfony Form component bug or a doctrine one?

Comment by Marco Pivetta [ 26/Feb/13 ]

Rémi Piotaix this is a problem of symfony forms, please report it on the symfony issue tracker (check if there's a similar open issue first) at https://github.com/symfony/symfony/issues/





[DDC-2306] Lazy loading associated entity's property causes identity loss when another association is set to fetch="EAGER" Created: 20/Feb/13  Updated: 29/Apr/14  Due: 22/Feb/13  Resolved: 26/Feb/13

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: Git Master
Fix Version/s: 2.4
Security Level: All

Type: Bug Priority: Critical
Reporter: Bill Schaller Assignee: Marco Pivetta
Resolution: Fixed Votes: 0
Labels: orm, proxy, unitofwork
Environment:

PHP 5.4 - IIS 7.0


Attachments: Zip Archive sandbox-uow-issue.zip    

 Description   

There appears to be a bug in UnitOfWork.php, introduced in Merge pull request #406 from Ocramius/DCOM-96. The relevant section is lines 2479-2495.

In the attached test sandbox, there are 4 entities.

User and Address have a many-many relationship via UserAddress – this more or less duplicates what I have in my actual application. There is another entity that both User and Address refer to in a one-to-many relationship – Zone.

When the Zone relationship on User and Address is set to fetch="LAZY", the problem is absent. When the relationship is set to fetch="EAGER", the problem manifests as such:

When I load a User via $em->find(), and then access properties on a related Address, the identity of the Address is lost. The same is true going in the other direction. I var_dump the Address before accessing its street property, and it shows up properly as an uninitialized proxy with just the id set. After I access the street property of the Address, var_dump shows the proxy is loaded and initialized, with all properties set except the identity, which is now null.

I stepped through the code using XDebug, and found that the referenced lines in UnitOfWork.php are setting the created Address entity's properties incorrectly, removing the identity from the generated entity. It seems to have something to do with the _hints parameter.

I'm not sure what the fix is, because I am not familiar enough with this part of the code and what it is intended to do. I assume that this is not intended behavior.

I've included my test case sandbox, which references ../../../../autoload.php to load Doctrine. This was tested against doctrine2/master as of today.



 Comments   
Comment by Marco Pivetta [ 21/Feb/13 ]

I've created a branch with a fix at https://github.com/Ocramius/doctrine2/compare/hotfix;DDC-2306

Basically, what was happening here is a really nasty one:

The UnitOfWork did consider the `Zone` entity as if it was a `User` entity (not comparing classnames, basically). Since the identifier was also the same in this case, the two entities were compared as if the newly loaded `Zone` had to replace the existing `User` proxy.

Thus, the proxy was marked as un-managed and trashed (and so the identifier was also nulled).

Please pull the branch and give it a try. I'll re-read it tomorrow and then open a PR.

Comment by Bill Schaller [ 21/Feb/13 ]

This fixes the problem for the test case and for my app. Excellent speedy fix, thanks

Comment by Benjamin Eberlei [ 21/Feb/13 ]

A related Github Pull-Request [GH-585] was opened
https://github.com/doctrine/doctrine2/pull/585

Comment by Benjamin Eberlei [ 26/Feb/13 ]

A related Github Pull-Request [GH-585] was closed
https://github.com/doctrine/doctrine2/pull/585

Comment by Doctrine Bot [ 29/Apr/14 ]

A related Github Pull-Request [GH-585] was closed:
https://github.com/doctrine/dbal/pull/585





[DDC-2219] computeChangeSets array_merging for associationMappings problem ? Created: 02/Jan/13  Updated: 07/Jan/13

Status: Open
Project: Doctrine 2 - ORM
Component/s: None
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Documentation Priority: Major
Reporter: yohann.poli Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 0
Labels: unitofwork


 Description   

Is this normal that when i call "$changeset = $unitOfWork->getEntityChangeSet($myObject);", it only return changes of root Object, all changes in sub collection (OneToMany) are less (not merging in the changeset) ?

Is there an issue for that?



 Comments   
Comment by Marco Pivetta [ 02/Jan/13 ]

Changesets of collections are computed separately from those of entities.

Comment by yohann.poli [ 02/Jan/13 ]

Have to call the compute method for each collection of the entity ?

Comment by Benjamin Eberlei [ 06/Jan/13 ]

Yes you have to, but this kind of operation seems weird. What are you trying to achieve.

Comment by yohann.poli [ 07/Jan/13 ]

I manage a complex entity who have a collection entity (each entity in this collection have another collection entity) attributes and i need to now if the flush method has "really" execute an update.

For example if the level 3 entity is update, i have to know in the root entity all changes apply in child...





[DDC-2179] Transactions should sent in group not chunked Created: 29/Nov/12  Updated: 30/Nov/12  Resolved: 30/Nov/12

Status: Closed
Project: Doctrine 2 - ORM
Component/s: Mapping Drivers
Affects Version/s: 2.2, 2.3, Git Master
Fix Version/s: None
Security Level: All

Type: Bug Priority: Critical
Reporter: Florin Patan Assignee: Marco Pivetta
Resolution: Invalid Votes: 0
Labels: unitofwork
Environment:

MySQL 5.5 / Percona



 Description   

In UnitOfWork::commit() it seems that a transaction is done like this:

  • will send separate queries for transaction start
  • compute the queries/send them to the db driver
  • execute the commit statement
  • optionally execute rollback

The question would be, should my webserver have some issues with resources, wouldn't this part of the code be a pain for the DB?

I don't know how mysql, for example, handles sending the transaction in chunks as opposed to sending it in 2/3 statements ( begin + ops and commit / + revert in case of failure) or in mySQL,l the transaction is evaluated on COMMIT statement only?

If my assumption about how MySQL works, locking everything as soon as the statement is on the server, then shouldn't Doctrine use a internal buffer for sending transactions to the DB driver in order to avoid all sorts of problems that appear in high concurency scenarios?

Best regards.



 Comments   
Comment by Marco Pivetta [ 30/Nov/12 ]

Invalid IMO. This is an over-complication that (in such high load scenarios) is handled by clustering/load balancing. Not a problem of the ORM, since smashing all statements together will just make it impossible to trap any problems.

Comment by Marco Pivetta [ 30/Nov/12 ]

This performance improvement has been discussed directly on IRC.

The original problem is related to deadlocks and small transactions, which is not anyway solved by this issue.

Otherwise, this improvement requires a PoC that shows that it is possible to have exceptions still showing the query that caused the failure.

Comment by Marco Pivetta [ 30/Nov/12 ]

Sorry, was unclear. I basically mean that any approach squashing the queries into a single chunk sent to the DB should also allow us to get computed insert IDs and eventual exceptions should bubble up with the query that caused them.





[DDC-2176] Illegal offset type in isset or empty in UnitOfWork Created: 28/Nov/12  Updated: 15/Feb/14  Resolved: 01/May/13

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3, 2.4
Fix Version/s: None

Type: Bug Priority: Minor
Reporter: Yves Berkholz Assignee: Benjamin Eberlei
Resolution: Duplicate Votes: 0
Labels: unitofwork

Issue Links:
Duplicate
duplicates DDC-1998 Problem when deleting with EntityMana... Resolved

 Description   

Steps to reproduce the problem?

  • A custom DBAL type, that extends a scalar build-in type e.g. DBAL\Types\StringType
  • convertToPHPValue of custom DBAL type returns an instance of a class (implements __toString method)
  • Custom DBAL type is used as primary key in an entity
  • initially persist entity and flush entity manager
  • modify entity (keep same primary key) and persist entity again causes:

    Warning: Illegal offset type in isset or empty in vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php line 2407

I guess the solution in Doctrine\ORM\Internal\Hydration namespace by explicit converting result of convertToPHPValue if result is not a scalar value.



 Comments   
Comment by Marco Pivetta [ 23/Jan/13 ]

This one will introduce way too much overhead. We don't really support identifiers that are custom object types.

What is the exact version of the ORM? I couldn't spot anything at line 2407.

Comment by Yves Berkholz [ 24/Jan/13 ]

I use a dev branch and updated the version since creation of the report, hence the line number changed to 2466.

UnitOfWork.php
} else {
	$entity = $this->newInstance($class);
	$oid    = spl_object_hash($entity);

	$this->entityIdentifiers[$oid]  = $id;
	$this->entityStates[$oid]       = self::STATE_MANAGED;
	$this->originalEntityData[$oid] = $data;

	$this->identityMap[$class->rootEntityName][$idHash] = $entity; // <- 2466

	if ($entity instanceof NotifyPropertyChanged) {
		$entity->addPropertyChangedListener($this);
	}

	$overrideLocalValues = true;
}

Ok, I understand the overhead problem. I only tried to create a custom enum type that is represented by a class.
But i solved this by converting the value within the getter/setter of entity class.
It would have been nice to do this in the DBAL type, but it works that way.
Therefore, you might close the report or move it on a far future version "wishlist".
Anyway, thank for your time.

Nevertheless the information you requested:
Composer: doctrine/orm [2.3.x-dev fdd0af3]
git reference: fdd0af34e6fced967b8751bc3e4792c11ef86d57

Additionally, exception trace might help

 
() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2466
 Symfony/Component/HttpKernel/Debug/ErrorHandler->handle() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php:2466
 Doctrine/ORM/UnitOfWork->createEntity() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php:135
 Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator->hydrateRowData() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator.php:50
 Doctrine/ORM/Internal/Hydration/SimpleObjectHydrator->hydrateAllData() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/Internal/Hydration/AbstractHydrator.php:111
 Doctrine/ORM/Internal/Hydration/AbstractHydrator->hydrateAll() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/Persisters/BasicEntityPersister.php:678
 Doctrine/ORM/Persisters/BasicEntityPersister->load() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:171
 Doctrine/ORM/EntityRepository->findOneBy() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/EntityRepository.php:211
 Doctrine/ORM/EntityRepository->__call() at D:/projects/{projectname}/vendor/{customvendor}/lib-doctrine/src/{VendorNs}/Lib/Doctrine/DataFixtures/AbstractBaseFixture.php:123
 {VendorNs}/Lib/Doctrine/ORM/Repository/BaseLookupRepository->findOneById() at D:/projects/{projectname}/vendor/{customvendor}/lib-doctrine/src/{VendorNs}/Lib/Doctrine/DataFixtures/AbstractBaseFixture.php:123
 {VendorNs}/Lib/Doctrine/DataFixtures/AbstractBaseFixture->findPersistedEntity() at D:/projects/{projectname}/src/ProjectVendor/Bundle/DataFixturesBundle/Classes/ORM/LookupFixture.php:38
 {ProjectNs}/Bundle/DataFixturesBundle/Classes/ORM/LookupFixture->lookupentityDefaultBuilder() at D:/projects/{projectname}/src/ProjectVendor/Bundle/DataFixturesBundle/DataFixtures/ORM/Main/User/LookupData.php:59
 {ProjectNs}/Bundle/DataFixturesBundle/DataFixtures/ORM/Main/User/LookupData->onlinestatusBuild() at n/a:n/a
 call_user_func() at D:/projects/{projectname}/src/ProjectVendor/Bundle/DataFixturesBundle/Classes/ORM/LookupFixture.php:78
 {ProjectNs}/Bundle/DataFixturesBundle/Classes/ORM/LookupFixture->lookupentityDefaultLoader() at D:/projects/{projectname}/src/ProjectVendor/Bundle/DataFixturesBundle/DataFixtures/ORM/Main/User/LookupData.php:42
 {ProjectNs}/Bundle/DataFixturesBundle/DataFixtures/ORM/Main/User/LookupData->load() at D:/projects/{projectname}/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/AbstractExecutor.php:120
 Doctrine/Common/DataFixtures/Executor/AbstractExecutor->load() at D:/projects/{projectname}/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:83
 Doctrine/Common/DataFixtures/Executor/ORMExecutor->Doctrine/Common/DataFixtures/Executor/{closure}() at n/a:n/a
 call_user_func() at D:/projects/{projectname}/vendor/doctrine/orm/lib/Doctrine/ORM/EntityManager.php:223
 Doctrine/ORM/EntityManager->transactional() at D:/projects/{projectname}/var/cache/apps/web/local/jms_diextra/doctrine/EntityManager_50ffafed6b09f.php:31
 EntityManager50ffafed6b09f_546a8d27f194334ee012bfe64f629947b07e4919/__CG__/Doctrine/ORM/EntityManager->transactional() at D:/projects/{projectname}/vendor/doctrine/data-fixtures/lib/Doctrine/Common/DataFixtures/Executor/ORMExecutor.php:85
 Doctrine/Common/DataFixtures/Executor/ORMExecutor->execute() at D:/projects/{projectname}/vendor/doctrine/doctrine-fixtures-bundle/Doctrine/Bundle/FixturesBundle/Command/LoadDataFixturesDoctrineCommand.php:106
 Doctrine/Bundle/FixturesBundle/Command/LoadDataFixturesDoctrineCommand->execute() at D:/projects/{projectname}/vendor/symfony/symfony/src/Symfony/Component/Console/Command/Command.php:238
 Symfony/Component/Console/Command/Command->run() at D:/projects/{projectname}/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:192
 Symfony/Component/Console/Application->doRun() at D:/projects/{projectname}/vendor/symfony/symfony/src/Symfony/Bundle/FrameworkBundle/Console/Application.php:78
 Symfony/Bundle/FrameworkBundle/Console/Application->doRun() at D:/projects/{projectname}/vendor/symfony/symfony/src/Symfony/Component/Console/Application.php:105
 Symfony/Component/Console/Application->run() at D:/projects/{projectname}/bin/console.php:17
Comment by Benjamin Eberlei [ 01/May/13 ]

This works in this recent commit here, 0864ab8adac5c31d5ba97f0eb6792e5431a75b70. Should have worked before as well. Can you verify?

Comment by Benjamin Eberlei [ 01/May/13 ]

Related to DDC-1998, tests this behavior

Comment by Boy Baukema [ 28/Aug/13 ]

I'm still getting this issue, even after upgrading to 2.4.0-RC2.

Comment by Marco Pivetta [ 28/Aug/13 ]

Just a note: this is broken since 2.4 because before 2.4 we didn't convert meta fields via DBAL types. If your identifier is an object this will probably be the problem. We could cast it to string though.





[DDC-2167] [GH-522] [DDC-2166] Refactor identity hash generation Created: 25/Nov/12  Updated: 11/Nov/14  Resolved: 11/Nov/14

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: None
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Benjamin Eberlei Assignee: Marco Pivetta
Resolution: Incomplete Votes: 0
Labels: hashing, identifier, unitofwork


 Description   

This issue is created automatically through a Github pull request on behalf of beberlei:

Url: https://github.com/doctrine/doctrine2/pull/522

Message:

This work prepares for the merge of GH-232, allowing more complex and robust identifier hash generation.



 Comments   
Comment by Doctrine Bot [ 11/Nov/14 ]

A related Github Pull-Request [GH-522] was assigned:
https://github.com/doctrine/doctrine2/pull/522

Comment by Doctrine Bot [ 11/Nov/14 ]

A related Github Pull-Request [GH-522] was closed:
https://github.com/doctrine/doctrine2/pull/522





[DDC-2086] [GH-484] Prevented "Undefined index" notice when updating Created: 17/Oct/12  Updated: 31/Dec/13  Resolved: 25/Oct/12

Status: Resolved
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.3, Git Master
Fix Version/s: 2.3.1
Security Level: All

Type: Bug Priority: Trivial
Reporter: Benjamin Eberlei Assignee: Benjamin Eberlei
Resolution: Fixed Votes: 0
Labels: unitofwork
Environment:

OS X 10.8.2, PHP 5.3.17, Nginx 1.2.4 (php through FPM)



 Description   

This issue is created automatically through a Github pull request on behalf of jappie:

Url: https://github.com/doctrine/doctrine2/pull/484

Message:

While executing updates on an entity scheduled for update without a change-set, an "Undefined index" notice is raised.

This issue will occur when you manually call $em()->getUnitOfWork()->scheduleForUpdate() on an entity that hasn't changed. The entity will be included in UnitOfWork::$entityUpdates, but because there are no changes, its oid will not be included in UnitOfWork::$entityChangeSets.

I know I'm misusing scheduleForUpdate() a bit in this case, but the notice can easily be prevented with a !empty().



 Comments   
Comment by Benjamin Eberlei [ 22/Oct/12 ]

A related Github Pull-Request [GH-484] was closed
https://github.com/doctrine/doctrine2/pull/484

Comment by Fabio B. Silva [ 25/Oct/12 ]

Merged : https://github.com/doctrine/doctrine2/commit/cd7ef6e7a70d4ff4c25a85fdae71676aa6548ea6

Comment by Doctrine Bot [ 31/Dec/13 ]

A related Github Pull-Request [GH-484] was closed:
https://github.com/doctrine/dbal/pull/484





[DDC-1507] State change detection for version incrementation (for optimistic locking) in combination with orphanRemoval Created: 23/Nov/11  Updated: 26/Mar/15

Status: Open
Project: Doctrine 2 - ORM
Component/s: ORM
Affects Version/s: 2.1.4, 2.4.7
Fix Version/s: None
Security Level: All

Type: Improvement Priority: Major
Reporter: Georg Wächter Assignee: Benjamin Eberlei
Resolution: Unresolved Votes: 1
Labels: unitofwork, versioned

Issue Links:
Reference
is referenced by DDC-2864 New type of lock: OPTIMISTIC_FORCE_IN... Open
is referenced by DDC-3640 Force version increment via mapped pr... Resolved

 Description   

As i understand the documentation correctly, orphanRemoval associations have the meaning of a "part of" relationship. In the example (http://www.doctrine-project.org/docs/orm/2.0/en/reference/working-with-associations.html#orphan-removal) the adresses are part of the contact.

In my opinion we should reason that the state of the adress consists of the states of all nested contacts. As a consequence we should flag the contact as "dirty" when the adresses change.

This is relevant for optimistic locking scenarios or event handlers. In my application i tried to use optimistic locking for "contacts", which does not work if i don't change anything in the contact but only in the nested addresses.



 Comments   
Comment by Benjamin Eberlei [ 27/Nov/11 ]

This is still only an approvement, you can workaround this and handle is in your domain code.

Comment by Georg Wächter [ 27/Nov/11 ]

Not in all cases. The first problem is that my domain code can't modify the version property, doctrine seems to block any manipulations to it. So i'm not able to increment the variable myself.

The only solution is to implement optimistic locking on my own or to add a dummy persistent boolean field that gets inversed by my domain code .. which would trigger the doctrine implementation for the optimistic locking.

I think it's clear that the second option shouldn't be a choice. If doctrine doesn't handle the overall case exactly it should allow me to increment the version number myself.

Comment by Darien Hager [ 26/Mar/15 ]

Bump: I'm having a similar issue. Essentially I want to force the entity's version to be updated, even if there aren't any other "real" changes to go with it.

One idea for a workaround: Since version fields can only be integers or timestamps, define a "clearly wrong" magic value like "FORCE_INCREMENT". This would allow objects to signal without needing a reference to the EntityManager.

Would folks be open to a pull-request over this?





Generated at Mon Apr 27 20:54:52 UTC 2015 using JIRA 6.2.3#6260-sha1:63ef1d6dac3f4f4d7db4c1effd405ba38ccdc558.