Doctrine2: поле не может быть пустым при сохранении объекта - из-за отношений? - PullRequest
3 голосов
/ 12 января 2012

У меня есть объект с именем PrintJob, с полем ProductId (среди прочих). Когда я создаю новый экземпляр этой сущности и устанавливаю все поля, а затем использую persist, а затем flush, я получаю сообщение об ошибке, говорящее, что ProductId не может быть нулевым.

Я сделал var_dump() для переменной $productId, и получилось 47. Я также сделал var_dump() для getProductId() для новой сущности (до сохранения / сброса), и значение по-прежнему равно 47.

Я думаю, что проблема заключается в связи между сущностью PrintJob и сущностью Product. Вот отношения от сущности PrintJob:

/**
 * @OneToOne(targetEntity="Product")
 * @JoinColumn(name="ProductId", referencedColumnName="ProductId")
 */
private $product;

Я где-то читал, что в конструкторе вам нужно установить отношение к пустой коллекции, когда вы создаете новые сущности (а не загружаете существующие). Вот что я пытался сделать:

public function __construct()
{
    $this->product = new \Doctrine\Common\Collections\ArrayCollection();
}

Однако я получаю сообщение об ошибке:

Новый объект был обнаружен в связи, которая не была настроена для каскадного сохранения операций: Doctrine \ Common \ Collections \ ArrayCollection @ 000000002cb4568d00000000e92b0fce. Явно сохраняйте новый объект или настраивайте каскадные сохраняющиеся операции в отношении.

Любая помощь будет высоко ценится. Единственная найденная мною альтернатива - не использовать отношения: (

Я использую Doctrine 2.0.7.

Дополнительная информация:

Я не создаю новый объект Product; новый PrintJob связан через ProductId.

Вот как я создаю сущность - есть много других полей, которые я могу включить в код, если это полезно, но я думаю, что их не будет, так как проблема возникает только с ProductId ...

    // convert this quote to a print job
    $printJob = new \Dpp\Model\PrintJob;
    $printJob->setProductId($productId);
    // ... other fields ...
    \Dpp\System\Core::getEm()->persist($printJob);
    \Dpp\System\Core::getEm()->flush();

\ Dpp \ System \ Core :: getEm () возвращает EntityManager.

Отображение части из PrintJob в Product:

/**
 * @OneToOne(targetEntity="Product", cascade={"persist"})
 * @JoinColumn(name="ProductId", referencedColumnName="ProductId")
 */
private $product;

Нет эквивалентного сопоставления между Product и PrintJob.

Сущность продукта - только столбцы:

namespace Dpp\Model;
/**
 * @Entity
 * @Table(name="Brd_Products")
 */
class Product
{
/**
 * @Id @Column(type="integer", name="ProductId")
 * @GeneratedValue
 */
private $productId;

}

Дополнительная информация # 2:

@ JohnM2 указал, что мои ассоциации установлены неправильно. Итак, вот что у меня сейчас есть.

\ Dpp \ Model \ PrintJob

/**
 * @OneToOne(targetEntity="Product", cascade={"persist"})
 * @JoinColumn(name="ProductId", referencedColumnName="ProductId")
 */
private $product;

/**
 * @return \Dpp\Model\Product
 */
public function getProduct()
{
    return $this->product;
}

/**
 * @param \Dpp\Model\Product $product
 * @return void
 */
public function setProduct($product)
{
    $this->product = $product;
}

\ Dpp \ Model \ продукта

/**
 * @Id @Column(type="integer", name="ProductId")
 * @GeneratedValue
 */
private $productId;

public function getProductId()
{
    return $this->productId;
}

Код, который сохраняет новую сущность:

$productEntity = \Dpp\Query\Product::getById($productId);
$printJob = new \Dpp\Model\PrintJob;
$printJob->setProduct($productEntity);
\Dpp\System\Core::getEm()->persist($printJob);
\Dpp\System\Core::getEm()->flush();

Первая строка возвращает экземпляр \ Dpp \ Model \ Product. Я проверил, что $ productId установлен и что $ productEntity заполнен правильно.

К сожалению, теперь я получаю сообщение об ошибке в строке "persist":

Property productId does not exist

У меня есть связь с PrintJob, указывающая на Product. Нужен ли мне в противоположном направлении?

Хотя, надеюсь, почти там!

Редактировать

Не бери в голову, сам нашел этот последний. Мне нужно было установить имя столбца соединения на productId, а не ProductId. Исправлена. Спасибо всем :) 1079 *

Ответы [ 2 ]

2 голосов
/ 12 января 2012

Насколько я понимаю, у вас есть поле PrintJob::$product, а также поле PrintJob::$productId.И вы пытаетесь установить соединение между PrintJob и Product, используя явное productId поле «внешнего ключа» сущности PrintJob.

Но это не то, как работает ORM.Вам не нужно PrintJob::$productId, Doctrine создаст соответствующий внешний столбец из поля PrintJob::$product (то, что написано в аннотации @JoinColumn: @JoinColumn(name="ProductId", referencedColumnName="ProductId")).Таким образом, вместо этого вы должны установить связь между PrintJob и Product, назначив Product сущность (загруженную EntityManager) полю PrintJob::$product с помощью PrintJob->setProduct($product).

1 голос
/ 12 января 2012

Попробуйте добавить cascade={"persist"} к аннотации @OneToOne $product, например:

/**
 * @OneToOne(targetEntity="Product", cascade={"persist"})
 * @JoinColumn(name="ProductId", referencedColumnName="ProductId")
 */
private $product;

По умолчанию Doctrine неявно сохраняет ассоциации с другими сущностями, посмотрите на this

Также удалите эту строку $this->product = new \Doctrine\Common\Collections\ArrayCollection(); , не имеет смысла инициализировать то, что не является коллекцией, как коллекцию.

Надеюсь, это поможет

...