Understanding Doctrine Cascade Operations

2019-01-12 23:41发布

问题:

I want to check my understanding of cascade operations on Doctrine associations. For the purpose of this question, I have two models: Customer and Insuree.

If I define a many to many relationship between a Customer and Insuree and set cascade{"all"}, I understand that this will:

  • Adding a new insuree to a customer will persist this insuree and create an association in the join table.
  • Removing an insuree from the collection will detach the insuree from the customer and detach the customer from the insuree.
  • Deleting the customer will delete all insurees associated with the customer.

This is the definition of the association on Customers.

/**
 * @ORM\ManyToMany(targetEntity="Insuree", inversedBy="customers", cascade={"all"})
 * @ORM\JoinTable(name="customer_insuree",
 *      joinColumns={@ORM\JoinColumn(name="customer_id", referencedColumnName="id")},
 *      inverseJoinColumns={@ORM\JoinColumn(name="insuree_id", referencedColumnName="id")}
 * )
 */
protected $insurees;

If I define the inverse many to many relationship between an Insuree and Customer and set cascade{"all"}, I understand that this will:

  • Adding a new customer to an insuree will persist this customer and create an association in the join table.
  • Removing a customer from the collection will detach the customer from the insuree and detach the insuree from the customer.
  • Deleting the insuree will delete all customers associated with it.

This is the definition of the association on Insurees.

/**
 * @ORM\ManyToMany(targetEntity="Customer", mappedBy="insurees", cascade={"all"})
 */
protected $customers;

If I then define the relationship as to cascade on persist, merge and detach - deleting the insuree will not delete all associated customers - it will only remove the associations between the insuree and its customers?

/**
 * @ORM\ManyToMany(targetEntity="Customer", mappedBy="insurees", cascade={"persist", "merge", "detach"})
 */
protected $customers;

回答1:

persist & remove

You are correct about cascade={"persist"} meaning that persisting entity A, Doctrine will also persist all B entities in the Collection.

You are also correct about cascade={"remove"} meaning that removing entity A, Doctrine will also remove all B entities in the Collection.
But I doubt you would ever want to use this on a ManyToMany association, because when you remove entity A that cascades this operation to all B entities, those B entities might be associated to other A entities.

detach & merge

You are not correct about cascade={"detach"} and cascade={"merge"}:

Adding/removing entities from the Collection is something you need to do (in your code). Read about that here.

Detach means that you detach an entity from the EntityManager. The EntityManager will no longer manage that entity. This makes a detached entity the same as a newly instantiated entity, except that it's already in the database (but you made the EntityManager unaware of that).

In other words: cascade={"detach"} means that detaching entity A, Doctrine will also detach all B entities in the Collection.

Merge is the opposite of detach: You will merge a detached entity back into the EntityManager.
Do note that merge() will actually return a new managed object, the detached object you passed to it remains unmanaged.