【问题标题】:How to get the Doctrine cascade persisting working?如何让 Doctrine 级联持续工作?
【发布时间】:2015-07-31 21:28:37
【问题描述】:

我正在使用 Doctrine v2.4.2 开发 ZF2/Apigility 应用程序。

模型结构如下:anAssethasanAttachment(所以,这是1:1关系):

问题是我无法使用嵌入的Attachment 持久化Asset 并得到错误

23000, 1048, 列 'attachment_linkassetuuid' 不能为空

看来Doctrine先尝试保存Attachment,找不到attachment_linkassetuuid列的值,设置为null,外键约束坏了。

如何正确定义实体并使级联持续工作?


Asset

namespace MyDoctrineDataAccess\Model\Entity;
...
/**
 * Asset
 *
 * @ORM\Table(name="tbl_asset")
 * @ORM\Entity
 */
class Asset
{
    /**
     * @var string @ORM\Column(name="asset_uuid", type="string", length=36, nullable=false)
     * @ORM\Id
     */
    private $uuid;

    /**
     * @var \MyDoctrineDataAccess\Model\Entity\Attachment
     * @ORM\OneToOne(targetEntity="MyDoctrineDataAccess\Model\Entity\Attachment", mappedBy="asset", cascade={"remove", "persist"}, orphanRemoval=true)
     */
    private $attachment;
    ...
}

/**
 * @param \MyDoctrineDataAccess\Model\Entity\Attachment $attachment
 */
public function setAttachment($attachment) {
    $this->attachment = $attachment;
    return $this;
}

/**
 * @return the $attachment
 */
public function getAttachment() {
    return $this->attachment;
}

Attachment

namespace MyDoctrineDataAccess\Model\Entity;
...
/**
 * Attachment
 *
 * @ORM\Table(name="tbl_attachment", indexes={@ORM\Index(name="fk_attachment_uuid", columns={"attachment_linkassetuuid"})})
 * @ORM\Entity
 */
class Attachment
{
    /**
     *
     * @var string @ORM\Column(name="attachment_uuid", type="string", length=36, nullable=false)
     *      @ORM\Id
     */
    private $uuid;

    /**
     *
     * @var \MyDoctrineDataAccess\Model\Entity\Asset
     * @ORM\OneToOne(targetEntity="\MyDoctrineDataAccess\Model\Entity\Asset", inversedBy="attachment", cascade={"persist"})
     * @ORM\JoinColumn(name="attachment_linkassetuuid", referencedColumnName="asset_uuid")
     */
    private $asset;
    ...
}

/**
 *
 * @param \MyDoctrineDataAccess\Model\Entity\Asset $asset
 */
public function setAsset($asset)
{
    $this->asset = $asset;
    return $this;
}

/**
 *
 * @return the $asset
 * 
 */
public function getAsset()
{
    return $this->asset;
}

AssetService

namespace MyApi\V1\Rest\Asset;
...
class AssetService implements ServiceManagerAwareInterface
{
    ...
    public function saveAssets($data)
    {
        $entityManager = $this->serviceManager->get('Doctrine\ORM\EntityManager');
        $assetRepository = $entityManager->getRepository('My\Model\Entity\Asset');
        $hydratorManager = $this->serviceManager->get('hydratormanager');
        $hydrator = $hydratorManager->get('My\\Model\\Entity\\Hydrator\\EntityHydrator');
        foreach ($data as $assetData) {
            $asset = new Asset();
            $hydrator->hydrate($assetData, $asset);
            $entityManager->persist($asset);
            $entityManager->flush();
        }
    }
    ...
}

【问题讨论】:

  • 您的补水器确实工作正常吗,它是否为Asset Attachment 补水?另外,不是从hydrate 返回的水合对象,除非您已将其自定义为通过引用传递?例如$hydrated_object = $hydrator->hydrate($assetData, new Asset());
  • 您好,感谢您的评论!我刚刚检查过这个。在持久化 ($entityManager->persist($asset);) 的那一刻,Asset 实体已正确构建,其属性 attachmentAttachment 实体对象。

标签: php doctrine-orm zend-framework2 one-to-one laminas-api-tools


【解决方案1】:

由于@JoinColumn 默认nullabletrue according to the Doctrine documentation 我不太明白这个错误。但我确实看到在您的Attachment 实体@table 定义中您声明了一个索引:

indexes={@ORM\Index(name="fk_attachment_uuid", columns={"attachment_linkassetuuid"})}

尝试一次删除它,重建您的数据库并检查它是否解决了您的问题。如果没有,请发表评论,我会再看一看。

检查the OneToOne example in the Doctrine documentation。那里没有提到像你一样添加@index。 Doctrine 会自动将必要的索引添加到您的关系列中。

更新:

我认为问题可能在于Asset 不是关系的拥有方。检查文档here。尝试像这样更改您的 setAttachment 方法:

public function setAttachment($attachment) 
{
    $this->attachment = $attachment;
    $attachment->setAsset($this);
    return $this;
}

【讨论】:

  • 感谢您的回答!好吧,当然,这样我可以避免错误。但是您实际上建议的是删除外键约束(因为删除此索引是必要的)。下一步是创建attachment_linkassetuuid 列。但这只会导致attachment.attachment_linkassetuuid始终设置为NULL的数据库不一致。
  • @automatix Doctrine 应该负责这一切,您不必像以前那样手动添加@index...
  • 也许我误解了你。你不是这个意思,我应该删除索引(不可避免地是FOREIGN KEY),而只删除Attachment实体类注释中的@index。刚刚试了一下,但是Column 'attachment_linkassetuuid' cannot be null的错误依旧存在。
  • 好的。你能展示所有相关的setter和getter吗?所以在Asset你应该有setAttachment()getAttachment(),在Attachment你应该有setAsset()getAsset(),还请显示$data你水合物。
  • 我刚刚编辑了问题并添加了 getter 和 setter。我水合的数据是正确的,至少$entityManager->persist(...) 得到了一个完整的Asset 实体对象,其中嵌套了Attachment
猜你喜欢
  • 2023-04-04
  • 2013-11-05
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
  • 2013-03-05
  • 2016-12-04
  • 1970-01-01
  • 2015-10-23
相关资源
最近更新 更多