原则-删除实体并立即将其添加到阵列集合中



我有一个导入脚本,它读取XML文件并将数据添加到MySQL数据库中。xml文件包含匹配数据和关联的事件。

我有以下实体

  • MatchList(不是最好的名字,但其他主题)
  • MatchEvent

我的问题的相关关系:

内部匹配列表(反面)

/**
 * @OneToMany(targetEntity="MatchEvent", mappedBy="match", orphanRemoval=true)
 */
private $events;
public function __construct($uId)
{
    $this->setId($uId);
    $this->events = new ArrayCollection();
}

内部比赛事件(拥有方)

/**
 * @ManyToOne(targetEntity="MatchList", inversedBy="events")
 * @JoinColumn(name="match_id", referencedColumnName="id")
 */
private $match;

在导入脚本中,每个匹配项都有一个循环。在循环中,我想删除当前分配给该匹配的所有事件。然后,我想将xml文件中的新事件添加到该匹配中。

应该从数据库中完全删除这些事件。不仅仅是对比赛的引用。

的简化示例

XML内容

Match1
  EventA
  EventC
  EventF

导入之前

Match1
  EventA
  EventB

导入后应该是这样的

Match1
  EventA
  EventC
  EventF

所以一个事件可能是

  • delete+add(EventA)
  • 删除(EventB)
  • 添加(EventF)

这是因为XML包含事件的更新或更正。因此,唯一可靠的方法是删除所有分配的事件,并从最新的xml中添加当前有效的事件。

我的问题是删除部分同时立即添加。每项任务都在发挥作用。

我尝试了不同的方法(也阅读了条令文件),但我没能让它发挥作用。

遵循脚本的相关部分以及我尝试过的一些变体(注释掉)(不是整个代码。看看"…"我希望这足以理解我的问题/错误)

try
{
    foreach($matches as $matchNode)
    {
        $match = new MatchList($matchNode['uID']);
        ...
        $previousEvents = $match->getEvents();
        foreach($previousEvents as $previousEvent)
        {
            $match->removeEvent($previousEvent);
            //$previousEvent->setMatch(null);
            //$this->em->remove($previousEvent);
            //$this->em->persist($previousEvent);
        }
        foreach($teamData->Goal as $goal)
        {
            ...
            $event = new MatchEvent($match);
            $event->setPlayer($player);
            $event->setType($goal['Type']);
            $event->setPeriod($goal['Period']);
            $this->em->persist($event);
            $match->addEvent($event);
        }
        ...
        $this->em->persist($match);
    }
    $this->em->flush();
}
catch(Exception $e){}

无论我试过什么,它都不会像预期的那样奏效。有时我会出现错误(缺少级联持续存在),或者没有发生错误,但也没有删除。只有当我一次完成一项任务(删除或添加)时,它才有效。

我知道,只对反面进行的更改不会被条令所保存,所以我试图对MatchEvent实体调用remove。或者尝试取消设置整个ArrayCollection,并使用orphanRemoval删除实体。

我一直在努力。我希望有人能帮助我理解我做错了什么,正确的做法是什么。

谢谢

编辑

也许添加我尝试过的每一种变体都会有所帮助。

变体1)

之后不添加实体:从DB(GOOD)中删除事件

在后面添加实体:错误:通过关系"MatchList#events"找到了一个新实体,该实体未配置为级联实体的持久操作:MatchEvent@XYZ.(坏)

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
    $this->em->remove($previousEvent);
}

变体2)

之后不添加实体:从DB(GOOD)中删除事件

在后面添加实体:错误:通过关系"MatchList#events"找到了一个新实体,该实体未配置为级联实体的持久操作:MatchEvent@XYZ.(坏)

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->remove($previousEvent);
     $this->em->detach($previousEvent);
}

变体3)

之后没有添加实体:错误:通过关系"MatchList#events"找到了一个新实体,该实体未配置为级联实体的持久操作:MatchEvent@XYZ.(坏)

在之后添加实体:未尝试,因为删除操作都不起作用。

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->detach($previousEvent);
}

这应该有效,否则我误解了:http://docs.doctrine-project.org/projects/doctrine-orm/en/latest/reference/faq.html#i-呼叫-清除-一对多集合-但实体-未删除

变体4)

之后不添加实体:数据库中的数据加倍,因为没有删除任何事件,所有事件都以match_id NULL插入。(坏)

在之后添加实体:未尝试,因为删除操作都不起作用。

$previousEvents = $match->getEvents();
foreach($previousEvents as $previousEvent)
{
     $previousEvent->setMatch(null);
     $this->em->detach($previousEvent);
     $this->em->persist($previousEvent);
}

我找到了一个解决方案。

对于此解决方案,添加"orphanRemoval=true"非常重要。

/**
 * @OneToMany(targetEntity="MatchEvent", mappedBy="match", orphanRemoval=true)
 */
private $events;

在循环中,我使用removeElement从ArrayCollection中删除每个实体。因为orphanRemoval为true,所以实体也会被删除。

foreach($match->getEvents() as $event)
{
    $match->getEvents()->removeElement($event);
}

实体的添加与上面显示的相同。

我希望这个解释能帮助其他有同样问题的人。

最新更新