Doctrine2 oneToOne复合主键不可为空

时间:2014-08-30 21:59:35

标签: php mysql symfony doctrine-orm doctrine

我在Doctrine中的OneToOne关系上遇到了复合主键的问题。当一个对象没有关系(通常是可能的)时,我收到以下错误消息:

Doctrine\Common\Proxy\Exception\OutOfBoundsException: Missing value for 
primary key idEngine on Farkas\CoreBundle\Entity\Engine

我直接在Doctrine中找到了问题:

vendor/doctrine/orm/lib/Doctrine/ORM/UnitOfWork.php Line 2116

// TODO: Is this even computed right in all cases of composite keys?
foreach ($assoc['targetToSourceKeyColumns'] as $targetColumn => $srcColumn) {
    $joinColumnValue = isset($data[$srcColumn]) ? $data[$srcColumn] : null;
    if ($joinColumnValue !== null) {
        if ($targetClass->containsForeignIdentifier) {
            $associatedId[$targetClass->getFieldForColumn($targetColumn)] = $joinColumnValue;
        } else {
            $associatedId[$targetClass->fieldNames[$targetColumn]] = $joinColumnValue;
        }
    }
}
当外键为空时,

$joinColumnValue为空,因为包含行数据的数组$data没有关系字段的数组键。 todo评论告诉我复合键有问题吗?

这里是我的两个实体(只是一个小测试,不要考虑我的实体的逻辑^^):

第一

/**
 * Car
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Farkas\CoreBundle\Entity\CarRepository")
 */
class Car
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id_car", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $idCar;


    /**
     * @var string
     *
     * @ORM\Column(name="brand", type="string", length=255)
     */
    private $brand;

    /**
     * @var string
     *
     *
     * @ORM\OneToOne(targetEntity="Engine", mappedBy="car")
     * @ORM\JoinColumns(
     *    @ORM\JoinColumn(name="engine", referencedColumnName="id_engine"),
     *    @ORM\JoinColumn(name="country", referencedColumnName="country")
     * )
     */
    private $engine;

    /**
     * @var integer
     * @ORM\Id
     * @ORM\Column(name="country", type="integer")
     */
    private $country;
}

第二

/**
 * Engine
 *
 * @ORM\Table()
 * @ORM\Entity(repositoryClass="Farkas\CoreBundle\Entity\EngineRepository")
 */
class Engine
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id_engine", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="NONE")
     */
    private $idEngine;

    /**
     * @var string
     *
     * @ORM\Column(name="engineName", type="string", length=255)
     */
    private $engineName;

    /**
     * @var string
     *
     * @ORM\Column(name="description", type="string", length=255)
     */
    private $description;

    /**
     * @var integer
     * @ORM\Id
     * @ORM\Column(name="country", type="integer")
     */
    private $country;

    /**
     * @var integer
     *
     * @ORM\OneToOne(targetEntity="Car", inversedBy="engine")
     * @ORM\JoinColumns(
     *    @ORM\JoinColumn(name="car_id", referencedColumnName="id_car"),
     *    @ORM\JoinColumn(name="country", referencedColumnName="country")
     * )
     */
    private $car;
}

当我尝试执行findAll()时,我收到了上面的错误消息。当我直接在MySQL中执行生成的SQL时,一切看起来都很好:

SELECT t0.id_car AS id_car1, t0.brand AS brand2, t0.country AS country3, 
t0.engine AS engine4, t0.country AS country5 FROM Car t0

这意味着,水合作用不能与空的oneToOne关系一起使用。

1 个答案:

答案 0 :(得分:1)

(代表OP发表。)

正如所料,这只是我身边的一个错误。这是解决方案:

汽车实体

/**
 * @var string
 *
 *
 * @ORM\OneToOne(targetEntity="Engine", mappedBy="car")
 * @ORM\JoinColumns(
 *    @ORM\JoinColumn(name="fk_engine", referencedColumnName="id_engine"),
 *    @ORM\JoinColumn(name="fk_engine_country", referencedColumnName="country")
 * )
 */
private $engine;

引擎实体

/**
 * @var integer
 *
 * @ORM\OneToOne(targetEntity="Car", inversedBy="engine")
 * @ORM\JoinColumns(
 *    @ORM\JoinColumn(name="fk_car", referencedColumnName="id_car"),
 *    @ORM\JoinColumn(name="fk_car_country", referencedColumnName="country")
 * )
 */
private $car;

连接列的名称是一个属性,将作为db内的关系字段创建。我已经在表格中有一个名称为country的属性。所以最后名称始终是识别关系的外键。