(doctrine2 + symfony2) каскадное удаление: нарушение ограничения целостности 1451
во-первых, извините за мой плохой английский...
Я получил четыре сущности: User, Application, Bundle & Entity. Вот их отношения (с каскадным сохранением и удалением, см. код ниже):
- пользователей 1-n приложение
- приложение 1-n Bundle
- Bundle 1-n сущности
он работает нормально. Но пользователь может иметь два своих объекта по умолчанию, и мне нужно получить к ним доступ непосредственно.
поэтому я добавляю пользователю два поля, entity1 & entity2, с 1-1 отношения. И теперь мое приложение падает:
An exception occurred while executing 'DELETE FROM bundle WHERE id = ?' with params {"1":13}:
SQLSTATE[23000]: Integrity constraint violation: 1451 Cannot delete or update a parent row: a foreign key constraint fails (`misc`.`entity`, CONSTRAINT `FK_E284468F1FAD9D3` FOREIGN KEY (`bundle_id`) REFERENCES `bundle` (`id`))
Я пробовал несколько вещей, включая те, которые основаны в этот пост, но я не смог это исправить.
любая помощь приветствуется, заранее спасибо.
EDIT: мне нужно указать, что отношения User - >Entity являются optionnal: entity1 & entity2 пользователя может быть null. Ошибка происходит даже если они оба равны нулю.
вот мои определения сущностей:
# User :
/**
* @ORMOneToMany(targetEntity="sfCommandsContentBundleEntityApplication", mappedBy="user", cascade={"remove"}, orphanRemoval=true)
* @ORMOrderBy({"name" = "ASC"})
*/
protected $applications;
/**
* @ORMOneToOne(targetEntity="sfCommandsContentBundleEntityEntity")
* @ORMJoinColumn(name="entity1_id", referencedColumnName="id")
*/
private $entity1;
/**
* @ORMOneToOne(targetEntity="sfCommandsContentBundleEntityEntity")
* @ORMJoinColumn(name="entity2_id", referencedColumnName="id")
*/
private $entity2;
#Application :
/**
* @ORMOneToMany(targetEntity="sfCommandsContentBundleEntityBundle", mappedBy="application", cascade={"remove"}, orphanRemoval=true)
* @ORMOrderBy({"name" = "ASC"})
*/
protected $bundles;
/**
* @ORMManyToOne(targetEntity="sfCommandsUserBundleEntityUser", inversedBy="applications", cascade={"persist"})
* @ORMJoinColumn(name="user_id", referencedColumnName="id")
*/
protected $user;
#Bundle :
/**
* @ORMManyToOne(targetEntity="sfCommandsContentBundleEntityApplication", inversedBy="bundles", cascade={"persist"})
* @ORMJoinColumn(name="application_id", referencedColumnName="id")
*/
protected $application;
/**
* @ORMOneToMany(targetEntity="sfCommandsContentBundleEntityEntity", mappedBy="bundle", cascade={"remove"}, orphanRemoval=true)
* @ORMOrderBy({"name" = "ASC"})
*/
protected $entitys;
#Entity :
/**
* @ORMManyToOne(targetEntity="sfCommandsContentBundleEntityBundle", inversedBy="entitys", cascade={"persist"})
* @ORMJoinColumn(name="bundle_id", referencedColumnName="id")
*/
protected $bundle;
4 ответов
Так, спасибо что французский форум, я исправил проблему.
Мне нужно добавить nullable=true & onDelete= "SET NULL" в @ORM\JoinColumn
вот работоспособная конфигурация, может быть, она кому-то поможет :
#User.
/**
* @ORM\OneToMany(targetEntity="\sfCommands\ContentBundle\Entity\Application", mappedBy="user", cascade={"remove"}, orphanRemoval=true)
* @ORM\OrderBy({"name" = "ASC"})
*/
protected $applications;
/**
* @ORM\OneToOne(targetEntity="\sfCommands\ContentBundle\Entity\Entity")
* @ORM\JoinColumn(name="entity1_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $entity1;
/**
* @ORM\OneToOne(targetEntity="\sfCommands\ContentBundle\Entity\Entity")
* @ORM\JoinColumn(name="entity2_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
private $entity2;
#Application.
/**
* @ORM\OneToMany(targetEntity="\sfCommands\ContentBundle\Entity\Bundle", mappedBy="application", cascade={"remove"}, orphanRemoval=true)
* @ORM\OrderBy({"name" = "ASC"})
*/
protected $bundles;
/**
* @ORM\ManyToOne(targetEntity="\sfCommands\UserBundle\Entity\User", inversedBy="applications", cascade={"persist"})
* @ORM\JoinColumn(name="user_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
protected $user;
#Bundle.
/**
* @ORM\ManyToOne(targetEntity="\sfCommands\ContentBundle\Entity\Application", inversedBy="bundles", cascade={"persist"})
* @ORM\JoinColumn(name="application_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
protected $application;
/**
* @ORM\OneToMany(targetEntity="\sfCommands\ContentBundle\Entity\Entity", mappedBy="bundle", cascade={"remove"}, orphanRemoval=true)
* @ORM\OrderBy({"name" = "ASC"})
*/
protected $entitys;
#Entity.
/**
* @ORM\ManyToOne(targetEntity="\sfCommands\ContentBundle\Entity\Bundle", inversedBy="entitys", cascade={"persist"})
* @ORM\JoinColumn(name="bundle_id", referencedColumnName="id", nullable=true, onDelete="SET NULL")
*/
protected $bundle;
используйте onDelete= "каскад", если вы используете аннотацию
/**
* @ORM\ManyToOne(targetEntity="Report", inversedBy="responses")
* @ORM\JoinColumn(name="reportId", referencedColumnName="id",onDelete="CASCADE")
*/
используйте onDelete: CASCADE, если вы используете yml
joinColumn:
name: pid
referencedColumnName: id
onDelete: CASCADE
onDelete= "каскад" также отлично работает. Но не забудьте запустить app / console doctrine: schema: update --force до того, как изменения уровня БД вступят в силу.
orphanRemoval несколько раз не работает, потому что это зависит от (получает schedulled в) PersistencCollection
. И мы могли бы позвонить ArrayCollection#removeElement()
.
Ниже приведен фрагмент PersistencCollection#remove()
if ($this->association !== null &&
$this->association['type'] & ClassMetadata::TO_MANY &&
$this->owner &&
$this->association['orphanRemoval']) {
$this->em->getUnitOfWork()->scheduleOrphanRemoval($removed);
}
и ArrayCollection этого не делает.