我有一个使用Symfony3 / Doctrine2 Rest Api的Angular4应用程序。
在Angular和Symfony中,我都有这些实体:
表和节点之间的关系是:
表(OneToMany)TableNode(ManyToOne)节点
什么是" ManyToMany"与属性的关系。
在Angular应用程序中,我创建了一个新表(形成一个TableModel,其具有与Symfony应用程序中的Table实体完全相同的属性)。 此表包含来自Api的几个节点实体(因此它们已存在于我的数据库中)。
我想要的是创建一个包含新TableNode实体的新表,每个TableNode应该包含现有的Node实体。
当我想在db中保存我的表时,我通过Put动作调用我的Api:
/**
* PUT Route annotation
* @Put("/tables")
*/
public function putTableAction(Request $request)
{
$em = $this->getDoctrine()->getManager('psi_db');
$serializer = $this->container->get('jms_serializer');
$dataJson = $request->query->get('table');
$table = $serializer->deserialize($dataJson, Table::class, 'json');
// Here, my $table has no id (that's ok), the TableNode subentity has no id (ok) and my Node subentity already have an id (because they come from the db)
$em->persist($table);
// Here, my $table has a new id (ok), my TableNode has a new id (ok) BUT my Node subentity have a NEW id, so it will be duplicated
$em->flush();
$view = $this->view();
$view->setData($table);
return $this->handleView($view);
}
我尝试使用$ em-> merge($ table)而不是$ em-> persist($ table)并且我的节点子实体保留了自己的id(因此它们可能不会在flush中重复)但是table和tableNode没有id(null)并且没有持久化。
我找到的唯一解决方案是遍历TableNode实体,从数据库中检索Node实体并执行tableNode-> setNode:
$tns = $table->getTableNodes();
foreach ($tns as $tn) {
$nodeId = $tn->getNode()->getId();
$dbNode = $nodeRepo->find($nodeId);
$tn->setNode($dbNode);
}
但它不是一个好的解决方案,因为我在循环中进行数据库搜索,而一个表可能包含超过一百个TableNode / Node,因此可能需要大量资源。
有没有人有更清洁的解决方案? 谢谢。
编辑:添加课程
表:
/**
* Table_
* Doctrine "Table" is a reserved name, so we call it Table_
*
* @ORM\Table(name="psi_table")
* @ORM\Entity(repositoryClass="AppBundle\Repository\Table_Repository")
*
* @ExclusionPolicy("all")
*/
class Table_
{
public function __construct()
{
$this->tNodes = new ArrayCollection();
}
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Expose
*/
private $id;
/**
* @var string
*
* @ORM\Column(name="name", type="string", length=255, nullable=true)
*
* @Expose
*/
private $name;
/**
* @var \stdClass
*
* @ORM\Column(name="author", type="object", nullable=true)
*
* @Expose
*/
private $author;
/**
* @var \stdClass
*
* @ORM\OneToMany(targetEntity="AppBundle\Entity\TableNode", mappedBy="table", cascade={"persist"})
*
* @Expose
* @Type("ArrayCollection<AppBundle\Entity\TableNode>")
* @SerializedName("tNodes")
*/
private $tNodes;
}
TableNode:
/**
* TableNode
*
* @ORM\Table(name="psi_table_node")
* @ORM\Entity(repositoryClass="AppBundle\Repository\TableNodeRepository")
*
* @ExclusionPolicy("all")
*/
class TableNode
{
public function __construct($table = null, $node = null, $position = null)
{
if($table) $this->table = $table;
if($node) $this->node = $node;
if($position) $this->position = $position;
}
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Expose
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="position", type="integer")
*
* @Expose
*/
private $position;
/**
* @var string
*
* @ORM\Column(name="groupSocio", type="string", nullable=true)
*
* @Expose
* @SerializedName("groupSocio")
*/
private $groupSocio;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Table_", inversedBy="tNodes", cascade={"persist"})
* @ORM\JoinColumn(nullable=false)
*
* @Expose
* @Type("AppBundle\Entity\Table_")
*/
private $table;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Node", inversedBy="tables", cascade={"persist", "merge"})
* @ORM\JoinColumn(nullable=false)
*
* @Expose
* @Type("AppBundle\Entity\Node")
*/
private $node;
}
节点:
/**
* TableNode
*
* @ORM\Table(name="psi_table_node")
* @ORM\Entity(repositoryClass="AppBundle\Repository\TableNodeRepository")
*
* @ExclusionPolicy("all")
*/
class TableNode
{
public function __construct($table = null, $node = null, $position = null)
{
if($table) $this->table = $table;
if($node) $this->node = $node;
if($position) $this->position = $position;
}
/**
* @var integer
*
* @ORM\Column(name="id", type="integer")
* @ORM\Id
* @ORM\GeneratedValue(strategy="AUTO")
*
* @Expose
*/
private $id;
/**
* @var integer
*
* @ORM\Column(name="position", type="integer")
*
* @Expose
*/
private $position;
/**
* @var string
*
* @ORM\Column(name="groupSocio", type="string", nullable=true)
*
* @Expose
* @SerializedName("groupSocio")
*/
private $groupSocio;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Table_", inversedBy="tNodes", cascade={"persist"})
* @ORM\JoinColumn(nullable=false)
*
* @Expose
* @Type("AppBundle\Entity\Table_")
*/
private $table;
/**
* @ORM\ManyToOne(targetEntity="AppBundle\Entity\Node", inversedBy="tables", cascade={"persist", "merge"})
* @ORM\JoinColumn(nullable=false)
*
* @Expose
* @Type("AppBundle\Entity\Node")
*/
private $node;
}
提交的数据(示例):
{"tNodes":[{"id":0,"position":0,"groupSocio":"group1","node":{"id":683,"frontId":"1502726228584","level":"synusy","repository":"baseveg","name":"A synusy from my Angular app!","geoJson":{"type":"FeatureCollection","features":[{"type":"Feature","properties":[],"geometry":{"type":"Point","coordinates":[-10.0634765625,42.0982224112]}}]},"lft":1,"lvl":0,"rgt":2,"children":[{"id":684,"frontId":"1502726228586","level":"idiotaxon","repository":"baseflor","name":"poa annua","coef":"1","geoJson":{"type":"FeatureCollection","features":[{"type":"Feature","properties":[],"geometry":{"type":"Point","coordinates":[-10.0634765625,42.0982224112]}}]},"lft":1,"lvl":0,"rgt":2,"validations":[{"id":171,"repository":"baseflor","repositoryIdTaxo":"7075","repositoryIdNomen":"50284","inputName":"poa annua","validatedName":"Poa annua L."}]}],"validations":[]}}]}
答案 0 :(得分:0)
putTableAction的目的是:
这意味着:
1.您无需提交Node的任何详细信息。 Id 字段就足够了:
{"tNodes":[{"id":0,"position":0,"groupSocio":"group1","nodeId": 683}]}
2.您可以向 TableNode 添加一个名为 $ nodeId 的字段,并将其映射到&#34; node&#34; DB中的字段。此字段的目的是简化反序列化,在所有其他地方您可以使用 $ node 字段。
/**
* @var integer
*
* @ORM\Column(name="node", type="integer")
*
* @Expose
*/
private $nodeId;