我有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会自动执行此操作,就像对ManyToMany关系一样,并且不明白为什么即使提到cascade={"persist", "remove"}
有更清洁的方法吗?
答案 0 :(得分:1)
首先,cascade={"persist", "remove"}
仅适用于您持久保存或删除Promotion
对象的PromotionCategory
父的情况。您尝试执行的操作是删除Promotion对象的PromotionCategory
子项,因此cascade
关键字在这种情况下无关紧要。
话虽如此,您的查询问题在于您未在查询中加入Promotion实体。在DELETE
语句中,Doctrine显然无法做到这一点,如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中对这个类似问题的回答。