it-swarm.com.de

(Doktrin2 + Symfony2) Kaskadieren Entfernen: Verletzung der Integritätsbedingung 1451

Zuerst entschuldige mich für mein schlechtes Englisch ...

Ich habe vier Entitäten: Benutzer, Anwendung, Bundle und Entität. Hier sind ihre Beziehungen (mit Kaskadierung persist & remove, siehe Code unten):

  • Benutzer 1-n Anwendung
  • Anwendung 1-n Bundle
  • Bündel 1-n Entität

Es funktioniert gut. Ein Benutzer kann jedoch zwei seiner Entitäten standardmäßig verwenden, und ich muss direkt auf sie zugreifen. 

Also füge ich bei User zwei Felder hinzu, entity1 & entity2, mit einer 1-1 Relation. Und jetzt stürzt meine App ab:

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`))

Ich habe verschiedene Dinge ausprobiert, einschließlich derer, die in diesem Beitrag gegründet wurden, aber ich konnte es nicht reparieren.

Jede Hilfe ist willkommen, danke im Voraus.

EDIT: Ich muss darauf hinweisen, dass User-> Entity-Beziehungen optional sind: Entity1 und Entity2 des Benutzers können Null sein. Der Fehler tritt auch dann auf, wenn beide null sind.

Hier sind meine Entitäten Definitionen:

# 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")
     */
    private $entity1;

    /**
     * @ORM\OneToOne(targetEntity="\sfCommands\ContentBundle\Entity\Entity")
     * @ORM\JoinColumn(name="entity2_id", referencedColumnName="id")
     */
    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")
     */
    protected $user;

#Bundle :
    /**
     * @ORM\ManyToOne(targetEntity="\sfCommands\ContentBundle\Entity\Application", inversedBy="bundles", cascade={"persist"})
     * @ORM\JoinColumn(name="application_id", referencedColumnName="id")
     */
    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")
     */
    protected $bundle;
13
bgaze

Also, dank diesem französischen Forum habe ich das Problem behoben.

Ich musste nullable = true & onDelete = "SET NULL" in @ORM\JoinColumn hinzufügen

Hier ist die funktionsfähige Konfiguration, vielleicht hilft sie jemandem:

#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;
33
bgaze

Verwenden Sie onDelete = "CASCADE", wenn Sie Annotation verwenden

/**
 * @ORM\ManyToOne(targetEntity="Report", inversedBy="responses")
 * @ORM\JoinColumn(name="reportId", referencedColumnName="id",onDelete="CASCADE")
 */

Verwenden Sie onDelete: CASCADE, wenn Sie yml verwenden

joinColumn:
      name: pid
      referencedColumnName: id
      onDelete: CASCADE
21
Zaheer Babar

onDelete = "CASCADE" funktioniert auch gut. Vergessen Sie jedoch nicht, die App/Konsolen-Doktrin auszuführen: schema: update --force, bevor Änderungen auf DB-Ebene wirksam werden. 

3
basejumper

orphanRemoval funktioniert manchmal nicht, da es von PersistencCollection abhängt (wird geplant). Und wir könnten ArrayCollection#removeElement() nennen.

Das folgende ist ein Ausschnitt der PersistencCollection#remove()

    if ($this->association !== null &&
        $this->association['type'] & ClassMetadata::TO_MANY &&
        $this->owner &&
        $this->association['orphanRemoval']) {
        $this->em->getUnitOfWork()->scheduleOrphanRemoval($removed);
    }

und ArrayCollection tut das nicht.

1
juanmf