8

I'm getting a foreign constraint violation when trying to delete an entity, containing unidirectional one-to-many associations. I have the following simple class:

class Dealer{

/**
 * @ManyToMany(targetEntity="Car", cascade={"persist", "remove"})
 * @JoinTable(name="dealer_cars",
 *      joinColumns={@JoinColumn(name="dealer_id", referencedColumnName="id")},
 *      inverseJoinColumns={@JoinColumn(name="car_id", referencedColumnName="id",
        unique=true)}
 *    )
 **/
  protected cars;
}

The Car object should not contain a relation to its owner in this case (hence the unidirectional relationship). If I try to delete a Dealer object containing associations to cars, I get the following constraint violation:

Cannot delete or update a parent row: a foreign key constraint fails 
(`application`.`dealer_cars`, CONSTRAINT `FK_E1BCEEEBC3C6F69F`
 FOREIGN KEY (`car_id`) REFERENCES `car` (`id`))'

I would get the same message if I tried to delete the dealer row manually from the database table, but I thought Doctrine, using cascade="remove", would take care of this for me.

If I change the association to a bidirectional association it works. Why does this not work with unidirectional associations?

Frederik Wordenskjold
  • 10,031
  • 6
  • 38
  • 57
  • unidirectional one-to-many associations ? this looks more like bi-directional many-to-many to me :D Did you drop your database and recreate or did you have any fixtures/data-leftovers in the database when you changed the schema ? – Nicolai Fröhlich May 28 '13 at 00:15
  • you want to delete the dealer without the car being lost , do i get this right? – Nicolai Fröhlich May 28 '13 at 00:20
  • 1
    It is Doctrines definition of unidirectional one-to-many. It is a many-to-many with a unique constraint. I want to delete the car, when the dealer is deleted as well. – Frederik Wordenskjold May 28 '13 at 00:22
  • But I found the problem. I needed to add a `onDelete="cascade"` attribute to the car_id column in the foreign key table. Which obviously makes sense! Thanks for the interest :) – Frederik Wordenskjold May 28 '13 at 00:23

1 Answers1

17

Use the Database level onDelete option with Doctrine

@ORM\JoinColumn(name="dealer_id", referencedColumnName="id",  onDelete="SET NULL")

explanation from here:

  • CASCADE will propagate the change when the parent changes. (If you delete a row, rows in constrained tables that reference that row will also be deleted, etc.)
  • SET NULL sets the column value to NULL when a parent row goes away.

  • RESTRICT causes the attempted DELETE of a parent row to fail.


... update your database schema prior to complaining it's not working :-)

app/console doctrine:schema:update --force

if this is not working due to foreign key errors go the hard way (in this order) :

  • app/console doctrine:database:drop
  • app/console doctrine:database:create
  • app/console doctrine:schema:update --force
  • ( optional: app/console doctrine:fixtures:load )
Community
  • 1
  • 1
Nicolai Fröhlich
  • 51,330
  • 11
  • 126
  • 130