我在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关系一起使用。
答案 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的属性。所以最后名称始终是识别关系的外键。