【问题标题】:How to perist only the first level of an entities hierarchy with Doctrine?如何使用 Doctrine 仅保留实体层次结构的第一级?
【发布时间】:2017-09-26 11:33:22
【问题描述】:

我正在将 ZF3 应用程序的 DBAL 迁移到 Doctrine,并希望逐步进行。目前我正在使用Mapper 对象的层次结构。类似FooEntity 层次结构中的每个实体都有一个相应的FooMapper。嵌套实体的保存由嵌套的Mappers 执行。每个Mappers 将其实体保存为Zend\Db\Sql\InsertZend\Db\Sql\Update,并为子实体调用正确的Mappers,例如BarMapperBarEntity

现在,在我开始使用像 cascade={"persist"} 这样的 Doctrine 便利功能之前,我想保留 Mapper 的层次结构,并使用 persist(...)flush() 执行嵌套实体的顶层保存.

但是当我尝试它时

public function save(AbstractDataObject $dataObject)
{
    $newLogicalConnection = $this->logicalConnectionMapper->save($dataObject->getLogicalConnection());
    $newUser = $this->userMapper->save($dataObject->getUser());

    $dataObject->setLogicalConnection($this->entityManager->find(LogicalConnection::class, $newLogicalConnection->getId()));
    $dataObject->setUser($this->entityManager->find(User::class, $newUser->getId()));

    $this->entityManager->persist($dataObject);
    $this->entityManager->flush();

    return $dataObject;
}

我收到一个错误

A new entity was found through the relationship 'MyNamespace\DataObject\AbstractEndpoint#externalServer' that was not configured to cascade persist operations for entity: MyNamespace\DataObject\ExternalServer@000000006098ccff0000000068c23676. To solve this issue: Either explicitly call EntityManager#persist() on this unknown entity or configure cascade persist  this association in the mapping for example @ManyToOne(..,cascade={"persist"}). If you cannot find out which entity causes the problem implement 'MyNamespace\DataObject\ExternalServer#__toString()' to get a clue.

因此,Doctrine 似乎尝试保存整个实体及其子实体,但此尝试在较低级别之一失败。但为什么?我没有激活任何cascade 选项,并希望 Doctrine 只保存顶层。

为什么 Doctrine 试图保存整个实体而不仅仅是顶层?以及如何让它只保存给定实体的顶层?

【问题讨论】:

  • 我认为没有办法。新的实体错误消息基本上是您需要启用级联的警告。鉴于您在两个对象之间存在关系,Doctrine 将尝试持久化它。您当然可以删除关系映射。
  • @Cerad 感谢您的评论。可能我理解cascade={"persist"}的意思错了。我的期望是/是,使用cascade={"persist"} 注释,相关对象将被保存,而没有 - 不是。但是如果没有cascade={"persist"}也能实现级联保存,那么这个注解有什么意义呢?
  • 又是一个警告。有些人喜欢显式地保留所有子实体,在这种情况下不需要级联并且警告消失。通常,关于 Doctrine ORM 的一件事是它只是以某些方式做事。你要么忍受它,要么不使用它。就个人而言,如果我已经有一个基于 dbal 的系统,那么我会坚持使用它。
  • @Cerad 那么,是否可以停用级联保存(但不删除关系及其注释)?

标签: php doctrine-orm orm doctrine persistence


【解决方案1】:

您收到此错误是因为您在 AbstractEndpoint->externalServer 中有一个新实体(尚未持久化)并且此字段未注释为 cascade={"persist"}

换句话说,您刚刚创建了一个新实体 ExternalServer 并没有将其持久化并将其添加为与 AbstractEndpoint->externalServer 实体的关系,该实体未注释为 cascade={"persist"}

所以 Doctrine 最终拥有了这个新实体,但不知道如何处理它。为了不丢失任何数据,会引发此异常。

要解决此问题,您可以做两件事:

  1. 在创建 ExternalServer 实体后立即添加 $this->entityManager->persist($externalServer);
  2. cascade={"persist"} 注释AbstractEndpoint->externalServer。您不想这样做,因为您只想将顶级实体保存到数据库中,因此您需要手动保存它或不要添加它是一个关系。

现在回答你的问题:

但是为什么呢?我没有激活任何级联选项,希望 Doctrine 只保存顶层。

不知何故,通过你的对象模型 Doctrine 中的关系下降到ExternalServer 实体并发现它处于非持久状态。您不能只保存顶级对象层次结构,并链接到关系数据库中不存在的记录。如果您不希望 Doctrine 为您执行此操作 - 您必须自己处理这种情况或从关系中删除未持久化的实体

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-03-02
    • 1970-01-01
    • 2017-10-17
    • 2011-10-13
    • 2019-04-29
    • 1970-01-01
    • 2020-09-30
    • 1970-01-01
    相关资源
    最近更新 更多