2014-08-30 2 views
2

У меня проблема с составным первичным ключом в отношении OneToOne в Доктрине. Когда один объект не имеет никакого отношения (что обычно возможно) я получил следующее сообщение об ошибке:Doctrine2 oneToOne составной первичный ключ не может быть нулевым

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

Я нашел проблему непосредственно в Учении:

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 говорит мне, что что-то не так с составными ключами?

Вот два моих Entities (только небольшой тест, не думайте о логике моих сущностей ^^):

1-й

/** 
* 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() Я получил сообщение об ошибке выше. Когда я выполнять сгенерированный SQL непосредственно в MySQL, все выглядит отлично:

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

просто идея, почему бы вам не заставить свой двигатель на вашем автомобиле присоединиться к просто двигателю, а затем включить страны автомобиля и двигателя в новый объект страны. Тогда у вас могут быть нулевые отношения между ними. –

+0

Пример действительно глупый. Вот как это выглядит для моего реального кода @work. –

ответ

1

(Опубликовано от имени ОП.)

Как и ожидалось, это была просто ошибка с моей стороны. Это решение:

автомобилей Entity

/** 
* @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; 

двигателя Entity

/** 
* @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; 

Название объединения столбца является атрибутом, который будет создан как отношение полей внутри БД , У меня уже был атрибут с именем страны внутри таблицы. Таким образом, наконец, имя всегда является внешним ключом для определения отношения.

Смежные вопросы