Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does orphanRemoval bypass onDelete?

Assume that we have two entities (Profile and Address). A profile can have many addresses. In that case we have:

Profile:
    ...
    fields:
        ...
    oneToMany:
        addresses:
            targetEntity: Address
            mappedBy: profile
            orphanRemoval: true
            
Address:
    ...
    fields:
        ...
    manyToOne:
        profile:
            targetEntity: Profile
            inversedBy: addresses
            joinColumn:
                name: profile_id
                referencedColumnName: id
                onDelete: cascade

Now, if I delete a profile that has many addresses:

$em->remove($profile);

How do the addresses get deleted?

Does Doctrine fetch all the addresses that are related to this profile and then delete them or does it only delete the profile and let the database handle the addresses?

I've found a few answers regarding Hibernate, but nothing about Doctrine.


EDIT: Add three note from Doctrine book

1.If an association is marked as CASCADE=REMOVE Doctrine 2 will fetch this association. If its a Single association it will pass this entity to EntityManager#remove(). If the association is a collection, Doctrine will loop over all its elements and pass them toEntityManager#remove(). In both cases the cascade remove semantics are applied recursively. For large object graphs this removal strategy can be very costly.

2.Using a DQL DELETE statement allows you to delete multiple entities of a type with a single command and without hydrating these entities. This can be very efficient to delete large object graphs from the database.

3.Using foreign key semantics onDelete="CASCADE" can force the database to remove all associated objects internally. This strategy is a bit tricky to get right but can be very powerful and fast. You should be aware however that using strategy 1 (CASCADE=REMOVE) completely by-passes any foreign key onDelete=CASCADE option, because Doctrine will fetch and remove all associated entities explicitly nevertheless.

like image 584
ghanbari Avatar asked Apr 18 '15 21:04

ghanbari


2 Answers

I do a test:

I first fetch Profile ( only profile without join ) and pass it to $em->remove($profile), then doctrine run a another query that fetch all Address that related to Profile (one query) and after it, doctrine run a delete query for each address that related to Profile, and in the final it delete Profile.

so, i can say that orphanRemoval is another type of cascading, as doctrine say:

orphanRemoval: There is another concept of cascading that is relevant only when removing entities from collections

and orphanRemoval bypass onDelete.

like image 111
ghanbari Avatar answered Sep 22 '22 05:09

ghanbari


There is a section on orphan removal in the Doctrine manual. There is also another question clarifying onDelete: cascade. I hope the two links help you further understand the topic.

Also, make sure that after $em->remove($profile); you call the $em->flush(); operation to sync the local unit of work to the database.

like image 29
Fabian Keller Avatar answered Sep 19 '22 05:09

Fabian Keller