Doctrine2:保存实体时,字段不能为null-由于关系


Doctrine2: field cannot be null when saving entity - due to relationships?

我有一个名为PrintJob的实体,它有一个ProductId字段(以及其他字段)。当我创建这个实体的新实例并设置所有字段,然后使用persistent和flush时,我得到一个错误,说ProductId不能为null。

我对$productId变量做了一个var_dump(),结果是47。我还在新实体的getProductId()上做了一个var_dump()(在persistent/flush之前),值仍然是47。

我认为问题出在PrintJob实体和Product实体之间的关系上。以下是来自PrintJob实体的关系:

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

我在某个地方读到,在构造函数中,当创建新实体(而不是加载现有实体)时,需要将关系设置为空集合。以下是我尝试做的:

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

然而,我得到了一个错误:

通过未配置为级联持久操作的关系找到了一个新实体:条令''通用''集合''ArrayCollection@000000002cb4568d00000000e92b0fce.显式持久化新实体或在关系上配置级联持久化操作。

任何帮助都将不胜感激。我找到的唯一选择是不使用关系:(

我使用的是条令2.0.7。

其他信息:

我不是在创建一个新的产品实体;正在通过ProductId链接新的PrintJob。

以下是我创建实体的方式-如果有用的话,我可以在代码中包括很多其他字段,但我想它们不会,因为问题只发生在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到产品的映射部分:

/**
 * @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''型号''产品

/**
 * @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是否已正确填充。

不幸的是,我现在在"持久"行上得到一个错误:

Property productId does not exist

我有一个从PrintJob指向Product的关系。我需要一个反方向的吗?

不过,我希望就快到了!

编辑

没关系,我自己找到了最后一个。我需要将联接列名设置为productId,而不是productId。固定的谢谢大家:)

据我所知,您有PrintJob::$product字段和PrintJob::$productId字段。您正试图使用PrintJob实体的显式productId"外键"字段在PrintJobProduct之间建立连接。

但这不是ORM的工作方式。您不需要PrintJob::$productId,Doctrine将从PrintJob::$product字段创建适当的外来列(@JoinColumn注释中写道:@JoinColumn(name="ProductId", referencedColumnName="ProductId"))。因此,您应该通过PrintJob->setProduct($product)Product实体(由EntityManager加载)分配给PrintJob::$product字段,在PrintJob和Product之间建立关联。

尝试将cascade={"persist"}添加到$product@OneToOne注释中,如下所示:

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

默认情况下,条令不会隐含地坚持与其他实体的关联,看看这个

还要删除这行$this->product = new 'Doctrine'Common'Collections'ArrayCollection(); ,将非集合的内容初始化为集合是没有意义的。

希望它能帮助