dqbn76906 2015-02-11 10:41
浏览 34

与Doctrine的多对多双向关系

I have got a many-to-many bidirectional relationship in Doctrine. It associates items with categories. The issue is that at the beginning I am assigning a category to a item correctly, but when I am trying to update an item's category then it fails, with a duplicate primary key.

These are some snippets from the code that might be helpful:

/**
 * @ORM\Table(name="item")
 * @ORM\Entity(repositoryClass="SomeBundle\Entity\Repository\ItemRepository")
 *
 */
class Item
{
/**
     * @ORM\ManyToMany(targetEntity="Category", inversedBy="items",   cascade={"persist"})
     **/
    private $categories;
 public function __construct()
    {
        $this->categories = new \Doctrine\Common\Collections\ArrayCollection();
    }
/**
     * @param Item $item
     */
    public function addItem(Item $item)
    {
        $this->items[] = $item;
    }

and

/**
 * Category
 *
 * @ORM\Table(name="category", indexes={@ORM\Index(name="category_parent", columns={"parent_id"})})
 * @ORM\Entity(repositoryClass="SomeBundle\Entity\Repository\CategoryRepository")
 * @ORM\HasLifecycleCallbacks
 */
class Category
{
    /**
     * @var integer
     *
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    private $id;

    /**
    * @ORM\ManyToMany(targetEntity="Item", mappedBy="categories", cascade={"persist"})
    * @ORM\JoinTable(name="item_category")
    **/
    private $items;

    public function __construct()
    {
        $this->items = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * @param Category $category
     */
    public function addCategory(Category $category)
    {
        $this->categories[] = $category;
        $category->addItem($this);
    }

UPDATE

 public function saveItem(Request $request)
    {
        $editMode = false;
        $itemId = $request->request->get('item_id');

        if (isset($itemId) && $itemId > 0) {
            $editMode = true;
        }

        $itemName = $request->request->get('itemName');
        $itemShortName= $request->request->get('itemShortName');

        $itemRepo = $this->getItemRepository();
        $item = $itemRepo->find($itemId);

        // get last Item Id
        if (!$editMode) {
            $newItem = new Item();
            $newItemId = rand(1000, 6000); // TODO
            $newItem->setId($newItemId);
            $newItem->setSection('ar');
            // by default the item is inactive
            $newItem->setActive(0);
        }

        //store the Item Type
        $itemType = new ItemType();
        $itemType->setTypeId($request->request->get('itemType'));

        if (!$editMode) {
            $itemType->setItemId($newItemId);
        }

        // store the data into the ItemTranslation
        if (!$editMode) {
            $newItemTranslation = new ItemTranslation();
            $newItemTranslation->setItemId($newItemId);
            $newItemTranslation->setLanguageId('1');
            $newItemTranslation->setItemName($itemName);
            $newItemTranslation->ItemShortname($itemShortName);
            $newItemTranslation->setTimestampAdd(new \DateTime());
            $this->em->persist($newItemTranslation);
        }

        //assign the respective Categories to the item
        $selectedCategoriesIds = $request->request->get('itemCategories');
        $categoryRepo = $this->getCategoryRepository();

        if (count($selectedCategoriesIds) > 0) {
            foreach ($selectedCategoriesIds as $selectedCategoryId) {
                $category = $categoryRepo->find($selectedCategoryId);
                if (is_object($item)) { //TODO
                    $item->addCategory($category);
                    $category->addItem($item);

                } else {
                    $newItem->addCategory($category);
                    $category->addItem($newItem);
                }

                if (!$editMode) {
                    $this->em->persist($newItem);
                }
            }
        }

        $this->em->flush();
    }

Error Message

An exception occurred while executing 'INSERT INTO item_category (item_id, category_id) VALUES (?, ?)' with params [2117, 1]:

SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '2117-1' for key 'PRIMARY'

** SECOND UPDATE **

I have added this if (is_object($item)) { $item->removeExistingCategories(); } just before:

if (count($selectedCategoriesIds) > 0) {
            foreach ($selectedCategoriesIds as $selectedCategoryId) {
                $category = $categoryRepo->find($selectedCategoryId);

and it seems that it works fine, with the exception that now the categories are being appeared twice in the UI, although the item_category table has been correctly populated.

OK, the last issue seems to have been sorted. I have made a mistake in itemsCategories iteration. :)

  • 写回答

1条回答 默认 最新

  • drn1008 2015-02-11 11:51
    关注

    Try removing cascade persist on Category Entity...you should do that only on the owning side of the relationship (Item in your case).

    评论

报告相同问题?

悬赏问题

  • ¥15 使用ue5插件narrative时如何切换关卡也保存叙事任务记录
  • ¥20 软件测试决策法疑问求解答
  • ¥15 win11 23H2删除推荐的项目,支持注册表等
  • ¥15 matlab 用yalmip搭建模型,cplex求解,线性化处理的方法
  • ¥15 qt6.6.3 基于百度云的语音识别 不会改
  • ¥15 关于#目标检测#的问题:大概就是类似后台自动检测某下架商品的库存,在他监测到该商品上架并且可以购买的瞬间点击立即购买下单
  • ¥15 神经网络怎么把隐含层变量融合到损失函数中?
  • ¥15 lingo18勾选global solver求解使用的算法
  • ¥15 全部备份安卓app数据包括密码,可以复制到另一手机上运行
  • ¥20 测距传感器数据手册i2c