【问题标题】:Doctrine cascade update - reset child entity before persist on update学说级联更新 - 在更新之前重置子实体
【发布时间】:2015-06-16 17:16:46
【问题描述】:

我有一个 Promotion 实体与 PromotionCategory 实体具有一对多关系。

Promotion 实体中我有:

/**
 * @var PromotionCategory[]
 * @OneToMany(targetEntity="AwinServices\Modules\AdvertiserPromotion\DomainLayer\Models\Promotion\Category", mappedBy="promotion", cascade={"persist", "remove"})
 */
public $promotionCategories;

在我拥有的PromotionCategory 实体中:

/**
 * @ManyToOne(targetEntity="AwinServices\Modules\AdvertiserPromotion\DomainLayer\Models\Promotion", inversedBy="promotionCategories")
 * @JoinColumn(name="promotionId", referencedColumnName="promotionId")
 **/
public $promotion;

我遇到的问题是,每次我使用新类别更新促销时,它都会继续为该促销创建新的 PromotionCategory 实体。

我想要的是重置该促销的先前类别,并为我正在传递的类别创建新行。

为了解决目前的问题,我正在尝试删除该促销的所有类别,然后再使用 DQL DELETE 语句:

$q = $this->doctrineEntityManager->createQuery("Delete from " . $this->getEntityClassname() . " r where r.promotion =" . $promotion->id);
$q->execute();

我认为 Doctrine 会像对多对多关系一样自动执行此操作,但我不明白为什么即使在提到 cascade={"persist", "remove"} 之后它也不对我的情况执行此操作

有没有更清洁的方法?

【问题讨论】:

  • 您不应该从 Promotion -> Promotion Category 中建立多对一关系吗?我显然不知道你想在你的代码中完成什么,但一个促销活动属于多个类别似乎很奇怪。
  • 另外,如果您在调试模式下使用 Symfony,您应该能够在执行 $q->execute() 时看到教义正在运行的 mysql 查询;
  • Decave,我的系统规定促销可以有多个类别,因此是一对多。 $q->execute() 我正在做的是我不想做的事情。我想在 Promotion 更新时使用一组新的 Id 来更新 Promotion Category 表,就像教义对多对多表所做的那样。

标签: mysql database symfony doctrine-orm innodb


【解决方案1】:

首先,cascade={"persist", "remove"} 仅适用于您保留或删除PromotionCategory 对象的Promotion 对象。您要做的是删除 Promotion 对象的 PromotionCategory 子级,因此在这种情况下,cascade 关键字无关紧要。

话虽如此,您的查询的问题在于您没有加入查询中的 Promotion 实体。 Doctrine 显然在 DELETE 语句中很难做到这一点,正如在 SO post 中所看到的那样。

正如@Danielle Suurlant 在那篇帖子中所说,一种方法是获取您要从数据库中删除的PromotionCategory 实体,然后使用实体管理器将它们删除:

$qb = $this->entityManager->createQueryBuilder();
$query = $qb->select('AwinServices\Modules\AdvertiserPromotion\DomainLayer\Models\Promotion\Category', 'category')
  ->innerJoin('category.promotion', 'promotion')
  ->where('promotion.id = :promotion_id')
  ->setParameter('promotion_id', $promotion->id)
  ->getQuery();
$results = $query->execute(); 

然后遍历结果并删除它们:

foreach ($results as $result) {
  $this->entityManager->remove($result);
}

并冲洗以摆脱它们:

$this->entityManager->flush();

再次感谢 Danielle Suurlant 在another post 中对类似问题的回答。

【讨论】:

  • 感谢您抽出宝贵的时间。这正是我目前正在做的事情,但是以更领域驱动的方式。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-19
  • 1970-01-01
相关资源
最近更新 更多