0

我正在解析一个包含许多项目的大型 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>

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

$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()after$em->persist($categoryEntity)解决了它,但我还不想刷新东西(或者就此而言,只刷新一个类别)。有很多未完成的事情要做,我不想打断我的交易。如果需要,我仍然希望能够回滚到最开始并排除所有未使用的类别(并且,显然,无需运行其他查询)。

我的问题是:有没有办法同时访问数据库和学说的内部实体映射来检索可能有或没有 ID 的实体?还是我必须自己创建这个映射,运行 DQL 并检查我的映射?

4

1 回答 1

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 中的引用进行操作。

于 2013-04-11T16:41:14.470 回答