From 6b5ef2a168250a8e6f269ceec9af824d976067f8 Mon Sep 17 00:00:00 2001 From: Matthias Pigulla Date: Fri, 23 Jun 2023 23:04:23 +0200 Subject: [PATCH] Remove remaining references to the `merge()` operation `EntityManager::merge()` has been deprecated in #8461 and removed in #9488. This PR removes a few remaining references and artefacts that - to my understanding - refer to it. --- docs/en/reference/attributes-reference.rst | 2 +- docs/en/reference/best-practices.rst | 2 +- docs/en/reference/inheritance-mapping.rst | 2 - .../limitations-and-known-issues.rst | 9 - .../reference/working-with-associations.rst | 2 +- docs/en/reference/working-with-objects.rst | 73 +------ docs/en/reference/xml-mapping.rst | 1 - ...eld-association-mappings-in-subclasses.rst | 2 +- doctrine-mapping.xsd | 1 - .../Mapping/Builder/AssociationBuilder.php | 8 - lib/Doctrine/ORM/Mapping/ClassMetadata.php | 9 +- lib/Doctrine/ORM/Mapping/MappingException.php | 2 +- .../Tests/Models/CMS/CmsPhonenumber.php | 2 +- tests/Doctrine/Tests/Models/CMS/CmsUser.php | 4 +- .../Models/DDC1872/DDC1872ExampleTrait.php | 2 +- .../Tests/Models/DDC964/DDC964User.php | 8 +- .../Tests/Models/Legacy/LegacyUser.php | 2 +- .../CompositeToOneKeyState.php | 2 +- .../Models/VersionedManyToOne/Article.php | 2 +- .../ORM/Functional/Ticket/DDC2602Test.php | 6 +- .../ORM/Functional/Ticket/DDC758Test.php | 186 ------------------ .../IdReassignmentAfterTruncateTest.php | 42 ++++ .../ORM/Mapping/MappingDriverTestCase.php | 6 - .../Doctrine.Tests.Models.CMS.CmsUser.dcm.xml | 2 - ...ine.Tests.Models.DDC964.DDC964User.dcm.xml | 2 - 25 files changed, 64 insertions(+), 315 deletions(-) delete mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php create mode 100644 tests/Doctrine/Tests/ORM/Functional/Ticket/IdReassignmentAfterTruncateTest.php diff --git a/docs/en/reference/attributes-reference.rst b/docs/en/reference/attributes-reference.rst index b5051f16e12..4f9ac1e5e3d 100644 --- a/docs/en/reference/attributes-reference.rst +++ b/docs/en/reference/attributes-reference.rst @@ -926,7 +926,7 @@ Example: #[OneToMany( targetEntity: "Phonenumber", mappedBy: "user", - cascade: ["persist", "remove", "merge"], + cascade: ["persist", "remove"], orphanRemoval: true) ] public $phonenumbers; diff --git a/docs/en/reference/best-practices.rst b/docs/en/reference/best-practices.rst index 002c130d5ce..b6f63a61b7b 100644 --- a/docs/en/reference/best-practices.rst +++ b/docs/en/reference/best-practices.rst @@ -43,7 +43,7 @@ should use events judiciously. Use cascades judiciously ------------------------ -Automatic cascades of the persist/remove/merge/etc. operations are +Automatic cascades of the persist/remove/etc. operations are very handy but should be used wisely. Do NOT simply add all cascades to all associations. Think about which cascades actually do make sense for you for a particular association, given the diff --git a/docs/en/reference/inheritance-mapping.rst b/docs/en/reference/inheritance-mapping.rst index a905e9a3deb..0cc29f9e0cf 100644 --- a/docs/en/reference/inheritance-mapping.rst +++ b/docs/en/reference/inheritance-mapping.rst @@ -387,7 +387,6 @@ Example: - @@ -499,7 +498,6 @@ Could be used by an entity that extends a mapped superclass to override a field - diff --git a/docs/en/reference/limitations-and-known-issues.rst b/docs/en/reference/limitations-and-known-issues.rst index bf1cb59d268..92b0cc8d472 100644 --- a/docs/en/reference/limitations-and-known-issues.rst +++ b/docs/en/reference/limitations-and-known-issues.rst @@ -65,15 +65,6 @@ Where the ``attribute_name`` column contains the key and The feature request for persistence of primitive value arrays `is described in the DDC-298 ticket `_. -Cascade Merge with Bi-directional Associations -~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ - -There are two bugs now that concern the use of cascade merge in combination with bi-directional associations. -Make sure to study the behavior of cascade merge if you are using it: - -- `DDC-875 `_ Merge can sometimes add the same entity twice into a collection -- `DDC-763 `_ Cascade merge on associated entities can insert too many rows through "Persistence by Reachability" - Custom Persisters ~~~~~~~~~~~~~~~~~ diff --git a/docs/en/reference/working-with-associations.rst b/docs/en/reference/working-with-associations.rst index 2c265679fa1..b5ca716ad07 100644 --- a/docs/en/reference/working-with-associations.rst +++ b/docs/en/reference/working-with-associations.rst @@ -415,7 +415,7 @@ Transitive persistence / Cascade Operations Doctrine ORM provides a mechanism for transitive persistence through cascading of certain operations. Each association to another entity or a collection of entities can be configured to automatically cascade the following operations to the associated entities: -``persist``, ``remove``, ``merge``, ``detach``, ``refresh`` or ``all``. +``persist``, ``remove``, ``detach``, ``refresh`` or ``all``. The main use case for ``cascade: persist`` is to avoid "exposing" associated entities to your PHP application. Continuing with the User-Comment example of this chapter, this is how the creation of a new user and a new diff --git a/docs/en/reference/working-with-objects.rst b/docs/en/reference/working-with-objects.rst index 3dc9378ee15..d7168609a1d 100644 --- a/docs/en/reference/working-with-objects.rst +++ b/docs/en/reference/working-with-objects.rst @@ -372,77 +372,6 @@ automatically without invoking the ``detach`` method: The ``detach`` operation is usually not as frequently needed and used as ``persist`` and ``remove``. -Merging entities ----------------- - -Merging entities refers to the merging of (usually detached) -entities into the context of an EntityManager so that they become -managed again. To merge the state of an entity into an -EntityManager use the ``EntityManager#merge($entity)`` method. The -state of the passed entity will be merged into a managed copy of -this entity and this copy will subsequently be returned. - -Example: - -.. code-block:: php - - merge($detachedEntity); - // $entity now refers to the fully managed copy returned by the merge operation. - // The EntityManager $em now manages the persistence of $entity as usual. - - -The semantics of the merge operation, applied to an entity X, are -as follows: - - -- If X is a detached entity, the state of X is copied onto a - pre-existing managed entity instance X' of the same identity. -- If X is a new entity instance, a new managed copy X' will be - created and the state of X is copied onto this managed instance. -- If X is a removed entity instance, an InvalidArgumentException - will be thrown. -- If X is a managed entity, it is ignored by the merge operation, - however, the merge operation is cascaded to entities referenced by - relationships from X if these relationships have been mapped with - the cascade element value MERGE or ALL (see ":ref:`transitive-persistence`"). -- For all entities Y referenced by relationships from X having the - cascade element value MERGE or ALL, Y is merged recursively as Y'. - For all such Y referenced by X, X' is set to reference Y'. (Note - that if X is managed then X is the same object as X'.) -- If X is an entity merged to X', with a reference to another - entity Y, where cascade=MERGE or cascade=ALL is not specified, then - navigation of the same association from X' yields a reference to a - managed object Y' with the same persistent identity as Y. - -The ``merge`` operation will throw an ``OptimisticLockException`` -if the entity being merged uses optimistic locking through a -version field and the versions of the entity being merged and the -managed copy don't match. This usually means that the entity has -been modified while being detached. - -The ``merge`` operation is usually not as frequently needed and -used as ``persist`` and ``remove``. The most common scenario for -the ``merge`` operation is to reattach entities to an EntityManager -that come from some cache (and are therefore detached) and you want -to modify and persist such an entity. - -.. warning:: - - If you need to perform multiple merges of entities that share certain subparts - of their object-graphs and cascade merge, then you have to call ``EntityManager#clear()`` between the - successive calls to ``EntityManager#merge()``. Otherwise you might end up with - multiple copies of the "same" object in the database, however with different ids. - -.. note:: - - If you load some detached entities from a cache and you do - not need to persist or delete them or otherwise make use of them - without the need for persistence services there is no need to use - ``merge``. I.e. you can simply pass detached objects from a cache - directly to the view. - Synchronization with the Database --------------------------------- @@ -553,7 +482,7 @@ during development. .. note:: Do not invoke ``flush`` after every change to an entity - or every single invocation of persist/remove/merge/... This is an + or every single invocation of persist/remove/... This is an anti-pattern and unnecessarily reduces the performance of your application. Instead, form units of work that operate on your objects and call ``flush`` when you are done. While serving a diff --git a/docs/en/reference/xml-mapping.rst b/docs/en/reference/xml-mapping.rst index 67edc4a4965..cf45b2dde02 100644 --- a/docs/en/reference/xml-mapping.rst +++ b/docs/en/reference/xml-mapping.rst @@ -691,7 +691,6 @@ specified by their respective tags: - ```` -- ```` - ```` - ```` - ```` diff --git a/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst b/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst index 8d36b30ef66..cd5e19cbd80 100644 --- a/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst +++ b/docs/en/tutorials/override-field-association-mappings-in-subclasses.rst @@ -66,7 +66,7 @@ which has mapping metadata that is overridden by the attribute above: #[Column(name: 'trait_foo', type: 'integer', length: 100, nullable: true, unique: true)] protected int $foo; - #[OneToOne(targetEntity: Bar::class, cascade: ['persist', 'merge'])] + #[OneToOne(targetEntity: Bar::class, cascade: ['persist'])] #[JoinColumn(name: 'example_trait_bar_id', referencedColumnName: 'id')] protected Bar|null $bar = null; } diff --git a/doctrine-mapping.xsd b/doctrine-mapping.xsd index a72530877aa..76109d525c0 100644 --- a/doctrine-mapping.xsd +++ b/doctrine-mapping.xsd @@ -35,7 +35,6 @@ - diff --git a/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php b/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php index 50817b4c39b..ea9e13c53b1 100644 --- a/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php +++ b/lib/Doctrine/ORM/Mapping/Builder/AssociationBuilder.php @@ -60,14 +60,6 @@ public function cascadeRemove(): static return $this; } - /** @return $this */ - public function cascadeMerge(): static - { - $this->mapping['cascade'][] = 'merge'; - - return $this; - } - /** @return $this */ public function cascadeDetach(): static { diff --git a/lib/Doctrine/ORM/Mapping/ClassMetadata.php b/lib/Doctrine/ORM/Mapping/ClassMetadata.php index 0694356a464..9096ddc4186 100644 --- a/lib/Doctrine/ORM/Mapping/ClassMetadata.php +++ b/lib/Doctrine/ORM/Mapping/ClassMetadata.php @@ -115,7 +115,6 @@ * isCascadeRemove: bool, * isCascadePersist: bool, * isCascadeRefresh: bool, - * isCascadeMerge: bool, * isCascadeDetach: bool, * isOnDeleteCascade?: bool, * isOwningSide: bool, @@ -618,7 +617,7 @@ class ClassMetadata implements PersistenceClassMetadata, Stringable * * - cascade (array, optional) * The names of persistence operations to cascade on the association. The set of possible - * values are: "persist", "remove", "detach", "merge", "refresh", "all" (implies all others). + * values are: "persist", "remove", "detach", "refresh", "all" (implies all others). * * - orderBy (array, one-to-many/many-to-many only) * A map of field names (of the target entity) to sorting directions (ASC/DESC). @@ -1585,7 +1584,7 @@ protected function _validateAndCompleteAssociationMapping(array $mapping): array // Cascades $cascades = isset($mapping['cascade']) ? array_map('strtolower', $mapping['cascade']) : []; - $allCascades = ['remove', 'persist', 'refresh', 'merge', 'detach']; + $allCascades = ['remove', 'persist', 'refresh', 'detach']; if (in_array('all', $cascades, true)) { $cascades = $allCascades; } elseif (count($cascades) !== count(array_intersect($cascades, $allCascades))) { @@ -1600,7 +1599,6 @@ protected function _validateAndCompleteAssociationMapping(array $mapping): array $mapping['isCascadeRemove'] = in_array('remove', $cascades, true); $mapping['isCascadePersist'] = in_array('persist', $cascades, true); $mapping['isCascadeRefresh'] = in_array('refresh', $cascades, true); - $mapping['isCascadeMerge'] = in_array('merge', $cascades, true); $mapping['isCascadeDetach'] = in_array('detach', $cascades, true); return $mapping; @@ -1624,7 +1622,6 @@ protected function _validateAndCompleteAssociationMapping(array $mapping): array * isCascadeRemove: bool, * isCascadePersist: bool, * isCascadeRefresh: bool, - * isCascadeMerge: bool, * isCascadeDetach: bool, * type: int, * originalField: string, @@ -1737,7 +1734,6 @@ protected function _validateAndCompleteOneToOneMapping(array $mapping): array * isCascadeRemove: bool, * isCascadePersist: bool, * isCascadeRefresh: bool, - * isCascadeMerge: bool, * isCascadeDetach: bool, * orphanRemoval: bool * } @@ -1780,7 +1776,6 @@ protected function _validateAndCompleteOneToManyMapping(array $mapping): array * isCascadeRemove: bool, * isCascadePersist: bool, * isCascadeRefresh: bool, - * isCascadeMerge: bool, * isCascadeDetach: bool, * type: int, * originalField: string, diff --git a/lib/Doctrine/ORM/Mapping/MappingException.php b/lib/Doctrine/ORM/Mapping/MappingException.php index 84d6d0f8993..f60ef595fdf 100644 --- a/lib/Doctrine/ORM/Mapping/MappingException.php +++ b/lib/Doctrine/ORM/Mapping/MappingException.php @@ -521,7 +521,7 @@ public static function invalidCascadeOption(array $cascades, string $className, $cascades = implode(', ', array_map(static fn (string $e): string => "'" . $e . "'", $cascades)); return new self(sprintf( - "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', 'merge', and 'detach'", + "You have specified invalid cascade options for %s::$%s: %s; available options: 'remove', 'persist', 'refresh', and 'detach'", $className, $propertyName, $cascades, diff --git a/tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php b/tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php index 7bfe373cb3d..1f23e4e0b60 100644 --- a/tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php +++ b/tests/Doctrine/Tests/Models/CMS/CmsPhonenumber.php @@ -21,7 +21,7 @@ class CmsPhonenumber public $phonenumber; /** @var CmsUser */ - #[ManyToOne(targetEntity: 'CmsUser', inversedBy: 'phonenumbers', cascade: ['merge'])] + #[ManyToOne(targetEntity: 'CmsUser', inversedBy: 'phonenumbers', cascade: [])] #[JoinColumn(name: 'user_id', referencedColumnName: 'id')] public $user; diff --git a/tests/Doctrine/Tests/Models/CMS/CmsUser.php b/tests/Doctrine/Tests/Models/CMS/CmsUser.php index 335525fb366..ea36ea7e3f6 100644 --- a/tests/Doctrine/Tests/Models/CMS/CmsUser.php +++ b/tests/Doctrine/Tests/Models/CMS/CmsUser.php @@ -42,7 +42,7 @@ class CmsUser public $name; /** @psalm-var Collection */ - #[OneToMany(targetEntity: 'CmsPhonenumber', mappedBy: 'user', cascade: ['persist', 'merge'], orphanRemoval: true)] + #[OneToMany(targetEntity: 'CmsPhonenumber', mappedBy: 'user', cascade: ['persist',], orphanRemoval: true)] public $phonenumbers; /** @psalm-var Collection */ @@ -62,7 +62,7 @@ class CmsUser #[JoinTable(name: 'cms_users_groups')] #[JoinColumn(name: 'user_id', referencedColumnName: 'id')] #[InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')] - #[ManyToMany(targetEntity: 'CmsGroup', inversedBy: 'users', cascade: ['persist', 'merge', 'detach'])] + #[ManyToMany(targetEntity: 'CmsGroup', inversedBy: 'users', cascade: ['persist', 'detach'])] public $groups; /** @var Collection */ diff --git a/tests/Doctrine/Tests/Models/DDC1872/DDC1872ExampleTrait.php b/tests/Doctrine/Tests/Models/DDC1872/DDC1872ExampleTrait.php index 735d014eb69..fdad6f4182b 100644 --- a/tests/Doctrine/Tests/Models/DDC1872/DDC1872ExampleTrait.php +++ b/tests/Doctrine/Tests/Models/DDC1872/DDC1872ExampleTrait.php @@ -21,7 +21,7 @@ trait DDC1872ExampleTrait protected $foo; /** @var DDC1872Bar */ - #[OneToOne(targetEntity: 'DDC1872Bar', cascade: ['persist', 'merge'])] + #[OneToOne(targetEntity: 'DDC1872Bar', cascade: ['persist'])] #[JoinColumn(name: 'example_trait_bar_id', referencedColumnName: 'id')] protected $bar; } diff --git a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php index d976a26be28..d5a6982a987 100644 --- a/tests/Doctrine/Tests/Models/DDC964/DDC964User.php +++ b/tests/Doctrine/Tests/Models/DDC964/DDC964User.php @@ -27,14 +27,14 @@ class DDC964User protected $id; /** @psalm-var Collection */ - #[ManyToMany(targetEntity: DDC964Group::class, inversedBy: 'users', cascade: ['persist', 'merge', 'detach'])] + #[ManyToMany(targetEntity: DDC964Group::class, inversedBy: 'users', cascade: ['persist', 'detach'])] #[JoinTable(name: 'ddc964_users_groups')] #[JoinColumn(name: 'user_id', referencedColumnName: 'id')] #[InverseJoinColumn(name: 'group_id', referencedColumnName: 'id')] protected $groups; /** @var DDC964Address */ - #[ManyToOne(targetEntity: DDC964Address::class, cascade: ['persist', 'merge'])] + #[ManyToOne(targetEntity: DDC964Address::class, cascade: ['persist'])] #[JoinColumn(name: 'address_id', referencedColumnName: 'id')] protected $address; @@ -110,7 +110,7 @@ public static function loadMetadata(ClassMetadata $metadata): void [ 'fieldName' => 'address', 'targetEntity' => 'DDC964Address', - 'cascade' => ['persist','merge'], + 'cascade' => ['persist'], 'joinColumns' => [['name' => 'address_id', 'referencedColumnMame' => 'id']], ], ); @@ -120,7 +120,7 @@ public static function loadMetadata(ClassMetadata $metadata): void 'fieldName' => 'groups', 'targetEntity' => 'DDC964Group', 'inversedBy' => 'users', - 'cascade' => ['persist','merge','detach'], + 'cascade' => ['persist','detach'], 'joinTable' => [ 'name' => 'ddc964_users_groups', 'joinColumns' => [ diff --git a/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php b/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php index 50e1231a596..e43bc6828bc 100644 --- a/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php +++ b/tests/Doctrine/Tests/Models/Legacy/LegacyUser.php @@ -47,7 +47,7 @@ class LegacyUser #[JoinTable(name: 'legacy_users_cars')] #[JoinColumn(name: 'iUserId', referencedColumnName: 'iUserId')] #[InverseJoinColumn(name: 'iCarId', referencedColumnName: 'iCarId')] - #[ManyToMany(targetEntity: 'LegacyCar', inversedBy: 'users', cascade: ['persist', 'merge'])] + #[ManyToMany(targetEntity: 'LegacyCar', inversedBy: 'users', cascade: ['persist'])] public $cars; public function __construct() diff --git a/tests/Doctrine/Tests/Models/MixedToOneIdentity/CompositeToOneKeyState.php b/tests/Doctrine/Tests/Models/MixedToOneIdentity/CompositeToOneKeyState.php index f3372e96763..f3f0d9a1289 100644 --- a/tests/Doctrine/Tests/Models/MixedToOneIdentity/CompositeToOneKeyState.php +++ b/tests/Doctrine/Tests/Models/MixedToOneIdentity/CompositeToOneKeyState.php @@ -22,7 +22,7 @@ class CompositeToOneKeyState /** @var Country */ #[Id] - #[ManyToOne(targetEntity: 'Country', cascade: ['MERGE'])] + #[ManyToOne(targetEntity: 'Country', cascade: [])] #[JoinColumn(referencedColumnName: 'country')] public $country; } diff --git a/tests/Doctrine/Tests/Models/VersionedManyToOne/Article.php b/tests/Doctrine/Tests/Models/VersionedManyToOne/Article.php index 41468abc189..8c57945ca7c 100644 --- a/tests/Doctrine/Tests/Models/VersionedManyToOne/Article.php +++ b/tests/Doctrine/Tests/Models/VersionedManyToOne/Article.php @@ -27,7 +27,7 @@ class Article public $name; /** @var Category */ - #[ManyToOne(targetEntity: 'Category', cascade: ['merge', 'persist'])] + #[ManyToOne(targetEntity: 'Category', cascade: ['persist'])] public $category; /** diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2602Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2602Test.php index d95a68db72c..281330cfd32 100644 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2602Test.php +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC2602Test.php @@ -172,7 +172,7 @@ class DDC2602User public $name; /** @var DDC2602Biography */ - #[OneToOne(targetEntity: 'DDC2602Biography', inversedBy: 'user', cascade: ['persist', 'merge', 'refresh', 'remove'])] + #[OneToOne(targetEntity: 'DDC2602Biography', inversedBy: 'user', cascade: ['persist', 'refresh', 'remove'])] #[JoinColumn(nullable: false)] public $biography; } @@ -187,7 +187,7 @@ class DDC2602Biography public $id; /** @var DDC2602User */ - #[OneToOne(targetEntity: 'DDC2602User', mappedBy: 'biography', cascade: ['persist', 'merge', 'refresh'])] + #[OneToOne(targetEntity: 'DDC2602User', mappedBy: 'biography', cascade: ['persist', 'refresh'])] public $user; /** @var string */ @@ -216,7 +216,7 @@ class DDC2602BiographyField public $label; /** @var ArrayCollection */ - #[OneToMany(targetEntity: 'DDC2602BiographyFieldChoice', mappedBy: 'field', cascade: ['persist', 'merge', 'refresh'])] + #[OneToMany(targetEntity: 'DDC2602BiographyFieldChoice', mappedBy: 'field', cascade: ['persist', 'refresh'])] public $choiceList; public function __construct() diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php deleted file mode 100644 index 461cf116d90..00000000000 --- a/tests/Doctrine/Tests/ORM/Functional/Ticket/DDC758Test.php +++ /dev/null @@ -1,186 +0,0 @@ -useModelSet('cms'); - - parent::setUp(); - } - - /** - * Helper method to set cascade to merge only - */ - private function setCascadeMergeFor($class): void - { - $metadata = $this->_em->getMetadataFactory()->getMetadataFor($class); - foreach ($metadata->associationMappings as $key => $associationMapping) { - $metadata->associationMappings[$key]['isCascadePersist'] = false; - $metadata->associationMappings[$key]['isCascadeMerge'] = true; - $metadata->associationMappings[$key]['isCascadeRemove'] = false; - $metadata->associationMappings[$key]['isCascadeDetach'] = false; - } - } - - /** - * Test that changing associations on detached entities and then cascade merging them - * causes the database to be updated with the new associations. - * This specifically tests adding new associations. - */ - public function testManyToManyMergeAssociationAdds(): void - { - $this->setCascadeMergeFor(CmsUser::class); - $this->setCascadeMergeFor(CmsGroup::class); - - // Put entities in the database - $cmsUser = new CmsUser(); - $cmsUser->username = 'dave'; - $cmsUser->name = 'Dave Keen'; - $cmsUser->status = 'testing'; - - $group1 = new CmsGroup(); - $group1->name = 'Group 1'; - - $group2 = new CmsGroup(); - $group2->name = 'Group 2'; - - $this->_em->persist($cmsUser); - $this->_em->persist($group1); - $this->_em->persist($group2); - $this->_em->flush(); - - $cmsUserId = $cmsUser->id; - $group1Id = $group1->id; - $group2Id = $group2->id; - - $this->_em->clear(); - - // Now create detached versions of the entities with some new associations. - $cmsUser = new CmsUser(); - $cmsUser->id = $cmsUserId; - $cmsUser->username = 'dave'; - $cmsUser->name = 'Dave Keen'; - $cmsUser->status = 'testing'; - $cmsUser->groups = new ArrayCollection(); - - $group1 = new CmsGroup(); - $group1->id = $group1Id; - $group1->name = 'Group 1'; - $group1->users = new ArrayCollection(); - - $group2 = new CmsGroup(); - $group2->id = $group2Id; - $group2->name = 'Group 2'; - $group2->users = new ArrayCollection(); - - $cmsUser->addGroup($group1); - $cmsUser->addGroup($group2); - - // Cascade merge of cmsUser followed by a flush should add in the bidirectional new many-to-many associations between the user and the groups - $this->_em->merge($cmsUser); - $this->_em->flush(); - - $this->_em->clear(); - - $cmsUsers = $this->_em->getRepository(CmsUser::class)->findAll(); - $cmsGroups = $this->_em->getRepository(CmsGroup::class)->findAll(); - - // Check the entities are in the database - self::assertEquals(1, count($cmsUsers)); - self::assertEquals(2, count($cmsGroups)); - - // Check the associations between the entities are now in the database - self::assertEquals(2, count($cmsUsers[0]->groups)); - self::assertEquals(1, count($cmsGroups[0]->users)); - self::assertEquals(1, count($cmsGroups[1]->users)); - - self::assertSame($cmsUsers[0]->groups[0], $cmsGroups[0]); - self::assertSame($cmsUsers[0]->groups[1], $cmsGroups[1]); - self::assertSame($cmsGroups[0]->users[0], $cmsUsers[0]); - self::assertSame($cmsGroups[1]->users[0], $cmsUsers[0]); - } - - /** - * Test that changing associations on detached entities and then cascade merging them causes the - * database to be updated with the new associations. - */ - public function testManyToManyMergeAssociationRemoves(): void - { - $this->setCascadeMergeFor(CmsUser::class); - $this->setCascadeMergeFor(CmsGroup::class); - - $cmsUser = new CmsUser(); - $cmsUser->username = 'dave'; - $cmsUser->name = 'Dave Keen'; - $cmsUser->status = 'testing'; - - $group1 = new CmsGroup(); - $group1->name = 'Group 1'; - - $group2 = new CmsGroup(); - $group2->name = 'Group 2'; - - $cmsUser->addGroup($group1); - $cmsUser->addGroup($group2); - - $this->_em->persist($cmsUser); - $this->_em->persist($group1); - $this->_em->persist($group2); - $this->_em->flush(); - - $cmsUserId = $cmsUser->id; - $group1Id = $group1->id; - $group2Id = $group2->id; - - $this->_em->clear(); - - // Now create detached versions of the entities with NO associations. - $cmsUser = new CmsUser(); - $cmsUser->id = $cmsUserId; - $cmsUser->username = 'dave'; - $cmsUser->name = 'Dave Keen'; - $cmsUser->status = 'testing'; - $cmsUser->groups = new ArrayCollection(); - - $group1 = new CmsGroup(); - $group1->id = $group1Id; - $group1->name = 'Group 1'; - $group1->users = new ArrayCollection(); - - $group2 = new CmsGroup(); - $group2->id = $group2Id; - $group2->name = 'Group 2'; - $group2->users = new ArrayCollection(); - - // Cascade merge of cmsUser followed by a flush should result in the association array collection being empty - $this->_em->merge($cmsUser); - $this->_em->flush(); - - $this->_em->clear(); - - $cmsUsers = $this->_em->getRepository(CmsUser::class)->findAll(); - $cmsGroups = $this->_em->getRepository(CmsGroup::class)->findAll(); - - // Check the entities are in the database - self::assertEquals(1, count($cmsUsers)); - self::assertEquals(2, count($cmsGroups)); - - // Check the associations between the entities are now in the database - self::assertEquals(0, count($cmsUsers[0]->groups)); - self::assertEquals(0, count($cmsGroups[0]->users)); - self::assertEquals(0, count($cmsGroups[1]->users)); - } -} diff --git a/tests/Doctrine/Tests/ORM/Functional/Ticket/IdReassignmentAfterTruncateTest.php b/tests/Doctrine/Tests/ORM/Functional/Ticket/IdReassignmentAfterTruncateTest.php new file mode 100644 index 00000000000..487654846f3 --- /dev/null +++ b/tests/Doctrine/Tests/ORM/Functional/Ticket/IdReassignmentAfterTruncateTest.php @@ -0,0 +1,42 @@ +createSchemaForModels(SomeEntity::class); + + $entity = new SomeEntity(); + $this->_em->persist($entity); + $this->_em->flush(); + + $this->_em->getConnection()->executeStatement('TRUNCATE TABLE some_table'); + + $entity = new SomeEntity(); + $this->_em->persist($entity); + $this->_em->flush(); + } +} + +/** + * @ORM\Entity + * @ORM\Table(name="some_table") + */ +class SomeEntity +{ + /** + * @ORM\Id + * @ORM\GeneratedValue() + * @ORM\Column(type="integer") + * + * @var int + */ + private $id; +} diff --git a/tests/Doctrine/Tests/ORM/Mapping/MappingDriverTestCase.php b/tests/Doctrine/Tests/ORM/Mapping/MappingDriverTestCase.php index f706c70b792..71e81067f8c 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/MappingDriverTestCase.php +++ b/tests/Doctrine/Tests/ORM/Mapping/MappingDriverTestCase.php @@ -359,7 +359,6 @@ public function testOwningOneToOneAssociation(ClassMetadata $class): ClassMetada self::assertFalse($class->associationMappings['address']['isCascadePersist']); self::assertFalse($class->associationMappings['address']['isCascadeRefresh']); self::assertFalse($class->associationMappings['address']['isCascadeDetach']); - self::assertFalse($class->associationMappings['address']['isCascadeMerge']); return $class; } @@ -373,7 +372,6 @@ public function testInverseOneToManyAssociation(ClassMetadata $class): ClassMeta self::assertTrue($class->associationMappings['phonenumbers']['isCascadeRemove']); self::assertFalse($class->associationMappings['phonenumbers']['isCascadeRefresh']); self::assertFalse($class->associationMappings['phonenumbers']['isCascadeDetach']); - self::assertFalse($class->associationMappings['phonenumbers']['isCascadeMerge']); self::assertTrue($class->associationMappings['phonenumbers']['orphanRemoval']); // Test Order By @@ -392,7 +390,6 @@ public function testManyToManyAssociationWithCascadeAll(ClassMetadata $class): C self::assertTrue($class->associationMappings['groups']['isCascadePersist']); self::assertTrue($class->associationMappings['groups']['isCascadeRefresh']); self::assertTrue($class->associationMappings['groups']['isCascadeDetach']); - self::assertTrue($class->associationMappings['groups']['isCascadeMerge']); self::assertFalse(isset($class->associationMappings['groups']['orderBy'])); @@ -621,7 +618,6 @@ public function testAssociationOverridesMapping(): void self::assertEquals($guestGroups['isCascadeRemove'], $adminGroups['isCascadeRemove']); self::assertEquals($guestGroups['isCascadePersist'], $adminGroups['isCascadePersist']); self::assertEquals($guestGroups['isCascadeRefresh'], $adminGroups['isCascadeRefresh']); - self::assertEquals($guestGroups['isCascadeMerge'], $adminGroups['isCascadeMerge']); self::assertEquals($guestGroups['isCascadeDetach'], $adminGroups['isCascadeDetach']); // assert not override attributes @@ -658,7 +654,6 @@ public function testAssociationOverridesMapping(): void self::assertEquals($guestAddress['isCascadeRemove'], $adminAddress['isCascadeRemove']); self::assertEquals($guestAddress['isCascadePersist'], $adminAddress['isCascadePersist']); self::assertEquals($guestAddress['isCascadeRefresh'], $adminAddress['isCascadeRefresh']); - self::assertEquals($guestAddress['isCascadeMerge'], $adminAddress['isCascadeMerge']); self::assertEquals($guestAddress['isCascadeDetach'], $adminAddress['isCascadeDetach']); // assert override @@ -1141,7 +1136,6 @@ public static function loadMetadata(ClassMetadata $metadata): void 0 => 'remove', 1 => 'persist', 2 => 'refresh', - 3 => 'merge', 4 => 'detach', ], 'mappedBy' => null, diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.CMS.CmsUser.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.CMS.CmsUser.dcm.xml index 5e9bb53580b..104ef15a567 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.CMS.CmsUser.dcm.xml +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.CMS.CmsUser.dcm.xml @@ -31,7 +31,6 @@ - @@ -44,7 +43,6 @@ - diff --git a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml index 3e6a91f39e1..cc4764b1b57 100644 --- a/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml +++ b/tests/Doctrine/Tests/ORM/Mapping/xml/Doctrine.Tests.Models.DDC964.DDC964User.dcm.xml @@ -14,7 +14,6 @@ - @@ -22,7 +21,6 @@ -