Doctrine:检索可能尚未保存到数据库的实体

时间:2013-04-11 14:39:13

标签: symfony doctrine

我正在解析一个包含很多项目的大型XML文件。每个项目都有很多类别,可以重复。这是一个XML示例。

<item>
    <category>Category1</category>
    <category>Category2</category>
    <category>Category3</category>
    <category>Category4</category>
    <category>Category5</category>
</item>
<item>
    <category>Category1</category>
    <category>Category2</category>
    <category>Category3</category>
    <category>Category7</category>
    <category>Category9</category>
</item>

使用doctrine来处理上面描述的多对多关系,我有一个这样的示例代码:

$em = $this->getDoctrine()->getEntityManager();

foreach ($items as $item) {

    [...]

    $categories = ... //Array with category names, parsed from the XML.

    foreach ($categories as $category) {

        //This will check if the 'item' entity 
        //already has a category with that name.
        $exists = $entity->getCategories()->exists(function($key, $element) use ($category) {
            return $category == $element->getName();
        });

        if (!$exists) {

            //If there's already one on the database, we'll load it.
            //Otherwise, we'll save a new Category..
            $query = $this->_entityManager->createQueryBuilder();
            $query->select('c')
                  ->from("MyBundle:Category, 'c');
                  ->where("c.name = :name")
                  ->setParameter("name", $category);

            }

            $result = $query->getQuery()->getOneOrNullResult();

            if ($result != null) {
                $item->addCategory($result);
            } else {
                $categoryEntity = new Category($category);
                $em->persist($categoryEntity);
                $item->addCategory($categoryEntity);
            }

        }

    }

}

事情是:当我完成所有项目的循环时,我只有flush()实体管理员。因此,$query->getQuery()->getOneOrNullResult() 始终会返回null,从而导致我创建重复的类别。

在上面的XML示例中,我有以下内容:

| item |
| 1    |
| 2    |

| category.id, category.name |
| 1,           Category1     |
| 2,           Category2     |
| 3,           Category3     |
| 4,           Category4     |
| 5,           Category5     |
| 6,           Category1     |
| 7,           Category2     |
| 8,           Category3     |
| 9,           Category7     |
| 10,          Category9     |

| item | category |
| 1    | 1        |
| 1    | 2        |
| 1    | 3        |
| 1    | 4        |
| 1    | 5        |
| 2    | 6        |
| 2    | 7        |
| 2    | 8        |
| 2    | 9        |
| 2    | 10       |

我想要以下内容:

| item |
| 1    |
| 2    |

| category.id, category.name |
| 1,           Category1     |
| 2,           Category2     |
| 3,           Category3     |
| 4,           Category4     |
| 5,           Category5     |
| 6,           Category7     |
| 7,           Category9     |

| item | category |
| 1    | 1        |
| 1    | 2        |
| 1    | 3        |
| 1    | 4        |
| 1    | 5        |
| 2    | 1        |
| 2    | 2        |
| 2    | 3        |
| 2    | 9        |
| 2    | 10       |

$em->flush()解决它之后简单地添加$em->persist($categoryEntity),但我不想再刷新内容(或者就此而言,只刷新一个类别)。有很多未完成的事情要做,我不想打断我的交易。我希望仍然能够回滚到最开始并排除所有未使用的类别,如果我需要(显然,不运行其他查询)。

我的问题是:有没有办法访问数据库和doctrine的内部实体映射,以检索可能有也可能没有ID的实体?或者我是否必须自己创建此映射,运行DQL并检查我的映射?

1 个答案:

答案 0 :(得分:1)

Doctrine2不能为你做到这一点, 但是很容易将新创建的类别存储在循环中,并在从数据库中获取MISS时检查它们。

    $_created_categories = array();

    if (!$exists) {
        // If there's already one on the database, we'll load it.
        // Otherwise, we'll save a new Category..

        $query = $this->_entityManager->createQueryBuilder();
        $query->select('c')
              ->from("MyBundle:Category, 'c');
              ->where("c.name = :name")
              ->setParameter("name", $category);

        $result = $query->getQuery()->getOneOrNullResult();

        if ($result) {
            $item->addCategory($result);
        elseif ( isset($_created_categories[$category]) ) {
            $item->addCategory($_created_categories[$category]);
        } else {
            $categoryEntity = new Category($category);
            $em->persist($categoryEntity);
            $item->addCategory($categoryEntity);

            $_created_categories[$category] = $categoryEntity;
        }
    }

将新类别实体存储在$_created_categories数组中没有内存开销,因为所有对象都是通过PHP中的引用进行操作的。