php - tutorial - ¿Cómo persistir solo el primer nivel de una jerarquía de entidades con Doctrine?
symfony 4 create entity from database (1)
Obtiene este error porque tiene una nueva entidad (no persistente) en AbstractEndpoint->externalServer
y este campo no está anotado como cascade={"persist"}
En otras palabras, acaba de crear una nueva entidad ExternalServer
y no la mantuvo y la agregó como una relación con AbstractEndpoint->externalServer
entity que no está anotada como cascade={"persist"}
Entonces Doctrine termina teniendo esta nueva entidad y no sabe qué hacer con ella. Para no perder ningún dato, esta excepción se plantea.
Para solucionar esto, puedes hacer dos cosas:
- Agregue
$this->entityManager->persist($externalServer);
justo después de crear la entidadExternalServer
- Anotar
AbstractEndpoint->externalServer
concascade={"persist"}
. Lo cual no quiere hacer porque solo quiere que la entidad de nivel superior se guarde en la base de datos, por lo que debe persistirla manualmente o NO agregar que se trata de una relación.
Y ahora respondiendo tu pregunta:
¿Pero por qué? No he activado ninguna opción de cascada y espero que Doctrine solo guarde el nivel superior.
De alguna manera, a través de las relaciones en su modelo de objeto, Doctrine baja a la entidad ExternalServer
y lo encuentra en estado no personalizado. No puede guardar solo el nivel superior de la jerarquía de objetos con un enlace a un registro inexistente en la base de datos relacional. Si no desea que Doctrine lo haga por usted, debe manejar esta situación usted mismo o eliminar las entidades no persistentes de las relaciones.
Estoy migrando el DBAL de una aplicación ZF3 a Doctrine y quiero seguir paso a paso. Actualmente estoy usando una jerarquía de objetos Mapper
. Cada entidad en la jerarquía FooEntity
tiene un FooMapper
acorde. El almacenamiento de entidades anidadas se realiza mediante Mapper
s anidado. Cada Mappers
guarda su entidad con Zend/Db/Sql/Insert
o Zend/Db/Sql/Update
y llama al Mapper
adecuado para las subentidades como BarMapper
para BarEntity
.
Ahora, antes de comenzar con las características de conveniencia de Doctrine como cascade={"persist"}
, quiero mantener la jerarquía del Mapper
y solo realizar el guardado del nivel superior de la entidad anidada con persist(...)
& flush()
.
Pero cuando lo intento
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;
}
Me sale un error
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.
Entonces, Doctrine parece intentar guardar la entidad completa con sus subentidades, y este intento falla en uno de los niveles inferiores. ¿Pero por qué? No he activado ninguna opción de cascade
y espero que Doctrine solo guarde el nivel superior.
¿Por qué Doctrine intenta salvar a toda la entidad y no solo al nivel superior? ¿Y cómo conseguirlo guardando solo el nivel superior de la entidad dada?