我正在将 ZF3 应用程序的 DBAL 迁移到 Doctrine,并希望一步一步地继续前进。目前,我使用的是Mapper
对象的层次结构。类似FooEntity
层次结构中的每个实体都有一个 根据FooMapper
。嵌套实体的保存由嵌套Mapper
执行。每个Mappers
都使用ZendDbSqlInsert
或ZendDbSqlUpdate
保存其实体,并为子实体调用正确的Mapper
,例如BarMapper
用于BarEntity
。
现在,在我开始使用 Doctrine 的便利功能(如cascade={"persist"}
)之前,我想保留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 'MyNamespaceDataObjectAbstractEndpoint#externalServer' that was not configured to cascade persist operations for entity: MyNamespaceDataObjectExternalServer@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 'MyNamespaceDataObjectExternalServer#__toString()' to get a clue.
因此,Doctrine似乎试图用它的子实体来拯救整个实体,而这种尝试在一个较低的层面上失败了。但是为什么?我没有激活任何cascade
选项,并期望 Doctrine 只保存顶级。
为什么教义试图拯救整个实体,而不仅仅是顶层?以及如何让它只保存给定实体的顶层?
您收到此错误是因为您在AbstractEndpoint->externalServer
中有一个新实体(尚未保留),并且此字段未注释为cascade={"persist"}
换句话说,您刚刚创建了一个新实体ExternalServer
并且没有保留它并将其添加为与未注释为AbstractEndpoint->externalServer
实体的关系cascade={"persist"}
因此,教义最终拥有了这个新实体,并且不知道如何处理它。为了不丢失任何数据,将引发此异常。
要解决此问题,您可以做两件事:
- 创建实体后立即添加
$this->entityManager->persist($externalServer);
ExternalServer
- 用
cascade={"persist"}
注释AbstractEndpoint->externalServer
。您不想这样做,因为您只想将顶级实体保存到数据库中,因此您需要手动保留它或不添加它是一个关系。
现在回答你的问题:
但是为什么?我没有激活任何级联选项,并希望 Doctrine 只保存顶级。
不知何故,通过对象模型中的关系,Doctrine 向下到ExternalServer
实体并发现它处于未持久状态。您不能只保存对象层次结构的顶层,并链接到关系数据库中不存在的记录。如果你不希望教义为你做这件事 - 你必须自己处理这种情况,或者从关系中删除未持久化的实体