简体   繁体   English

在Doctrine ORM 2中的类表继承上加入时,“主键elementId的缺失值”

[英]“Missing value for primary key elementId” when joining on Class Table Inheritance in Doctrine ORM 2

When I try to join on an inherited class I get an OutOfBoundsException from Doctrine with the error message above. 当我尝试加入继承的类时,我从Doctrine中收到带有以上错误消息的OutOfBoundsException。

I have defined following entities: 我定义了以下实体:

FormElement is the parent class FormElement是父类

/**
 * @ORM\Entity()
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="ETYP_ID", type="integer")
 * @ORM\DiscriminatorMap({
 *     1 = "DatetimeElement",
 *     3 = "ChoiceElement",
 *     4 = "TextElement",
 *     5 = "MatrixElement",
 *     6 = "HtmlElement"
 *     })
 * @Table(name="FORMELEMENT")
 */
abstract class Formelement {
    /**
     * @var integer
     * @ORM\Id()
     * @ORM\Column(name="ELE_ID", type="integer", nullable=false)
     */
    private $elementId;
}

ChoiceElement is a child class ChoiceElement是一个子类

/**
 * @ORM\Entity()
 * @ORM\Table(name="CHOICEELEMENT")
 */
class ChoiceElement extends Formelement {
    /**
     * @var integer
     * @ORM\Id()
     * @ORM\Column(name="CHOE_ID", type="integer", nullable=false)
     */
    private $id;
    /**
     * @var Choice[]|ArrayCollection
     * @ORM\OneToMany(targetEntity="Choice", mappedBy="choiceElement")
     */
    private $choices;

    public function getChoices(){
        return $this->choices;
    }
}

And Choice joins on ChoiceElement 选择加入ChoiceElement

/**
 * Class Choice
 * @package apps\dynfrm\models\Doctrine\entities
 * @ORM\Entity()
 * @ORM\Table(name="CHOICE")
 */
class Choice {
    /**
     * @var integer
     * @ORM\Id()
     * @ORM\Column(name="CHO_ID", type="integer", nullable=false)
     */
    private $id;

    /**
     * @var ChoiceElement
     * @ORM\ManyToOne(targetEntity="ChoiceElement", inversedBy="choices")
     * @ORM\JoinColumn(name="CHOE_ID", referencedColumnName="CHOE_ID", nullable=false)
     */
    private $choiceElement;
}

ChoiceElement is a FormElement and has multiple Choice s. ChoiceElement是一个FormElement并且具有多个Choice Everything works fine, even the call to ChoiceElement::getChoices() . 一切正常,即使调用ChoiceElement::getChoices() When I try to access the resulting ArrayCollection however, Doctrine throws error mentioned above. 但是,当我尝试访问生成的ArrayCollection时,Doctrine抛出上述错误。 I already did some digging using the debugger, but I don't understand if this is a bug or intended behaviour. 我已经使用调试器进行了一些挖掘,但是我不知道这是错误还是预期的行为。

I really hope someone can help me here. 我真的希望有人能在这里为我提供帮助。

Since ChoiceElement inherits Formelement , it does not need to have another id field. 由于ChoiceElement继承了Formelement ,因此不需要其他id字段。

As it is, when doctrine stumbles upon your ChoiceElement entity, it will define a composite primary key because two fields are marked with the @ORM\\Id annotation which is probably not the behaviour you want. ChoiceElement ,当学说偶然发现您的ChoiceElement实体时,它将定义一个复合主键,因为用@ORM\\Id批注标记了两个字段,这可能不是您想要的行为。 Thus, when it tries to join from your Choice entity, Doctrine complains because it only has one of the two needed keys that compose the primary key. 因此,当它尝试从您的Choice实体加入时,Doctrine会抱怨,因为它只有组成主键的两个必需键之一。

To solve this, simply remove the id attribute of your ChoiceElement entity. 要解决此问题,只需删除ChoiceElement实体的id属性。 Consequently, don't forget to update the referencedColumnName attribute of your choiceElement association. 因此,不要忘记更新您的choiceElement关联的referencedColumnName属性。 It should now be ELE_ID and not CHOE_ID . 现在应该是ELE_ID而不是CHOE_ID


Edit: Quick working example: 编辑:快速工作示例:

AbstractA.php AbstractA.php

/**
 * @ORM\Entity
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="integer")
 * @ORM\DiscriminatorMap({1 = "A"})
 */
abstract class AbstractA
{

    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;
}

A.php A.php

/** @ORM\Entity() */
class A extends AbstractA
{
    /**
     * @ORM\OneToMany(targetEntity="B", mappedBy="a")
     */
    private $bs;
}

B.php B.php

/** @ORM\Entity() */
class B
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
     * @ORM\ManyToOne(targetEntity="A", inversedBy="bs")
     */
    private $a;
}

Outputs the following schema: 输出以下架构:

CREATE TABLE abstract_a (id INT AUTO_INCREMENT NOT NULL, discr INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE a (id INT NOT NULL, PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
CREATE TABLE b (id INT AUTO_INCREMENT NOT NULL, a_id INT DEFAULT NULL, INDEX IDX_71BEEFF93BDE5358 (a_id), PRIMARY KEY(id)) DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE = InnoDB;
ALTER TABLE a ADD CONSTRAINT FK_E8B7BE43BF396750 FOREIGN KEY (id) REFERENCES abstract_a (id) ON DELETE CASCADE;
ALTER TABLE b ADD CONSTRAINT FK_71BEEFF93BDE5358 FOREIGN KEY (a_id) REFERENCES a (id);

And when I am trying to browse the array collection of B entities from an A entity, Doctrine triggers the following query successfully: 当我尝试从A实体浏览B实体的数组集合时,Doctrine成功触发了以下查询:

SELECT t0.id AS id_1, t0.a_id AS a_id_2 FROM b t0 WHERE t0.a_id = ?

In the same fashion, it is able to join the B table without a fuss if I ask it to. 以同样的方式,如果我要求的话,它也可以轻松加入B表。 Here is the query performed when I join a.bs : 这是我加入a.bs时执行的查询:

SELECT a0_.id AS id_0, b1_.id AS id_1, a0_.discr AS discr_2, b1_.a_id AS a_id_3 
FROM a a2_ 
  INNER JOIN abstract_a a0_ ON a2_.id = a0_.id 
  INNER JOIN b b1_ ON a2_.id = b1_.a_id 
WHERE a0_.id = ?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM