实体管理器没有预期具有关系的行为(不同的查询)


Entity manager has not expected behavior with relations (different queries)

我有以下DB/实体结构。因此,一个bug可以有多个产品。如果我使用不同的查询(不同的联接条件),我不会在脚本中得到预期的行为。我希望通过下面的代码示例更容易理解。

准备数据库:

INSERT INTO `bug` (`bug_id`, `description`, `status`) VALUES
    (1, 'Entity manager doesnt work as expected', 'open'),
    (2, 'Dotrine ORM issue', 'closed'),
    (3, 'Another bug', 'closed');
INSERT INTO `product` (`product_id`, `name`) VALUES
    (1, 'Doctrine 2'),
    (2, 'Zend Framwork 2'),
    (2, 'Another product');
INSERT INTO `bug_product` (`bug_id`, `product_id`) VALUES
    (1, 1),
    (1, 2),
    (2, 2),
    (3, 1),
    (3, 3);

存储库:

class BugRepository extends 'Doctrine'ORM'EntityRepository
{
    // here we want all bugs with only one product e.g. for a product overview
    public function findFilteredByProduct($productId)
    {
        $qb = $this->createQueryBuilder('bug')
            ->addSelect('product')
            ->join('bug.product', 'product')
            ->where('product = :productid')
            ->setParameter('productid', $productId);
        $query = $qb->getQuery();
        return $query->getResult();
    }
    // here we want all products for a bug, e.g. for bug details
    public function findWithProduct($bugId)
    {
        $qb = $this->createQueryBuilder('bug')
            ->addSelect('product')
            ->join('bug.product', 'product')
            ->where('bug.bugId = :bugId')
            ->setParameter('bugId', $bugId);
        $query = $qb->getQuery();
        return $query->getResult();
    }
}

控制器:

class IndexController extends 'Zend'Mvc'Controller'AbstractActionController
{
    public function testAction()
    {
         // assumed that $repoBug is initialized
        // only bugs which have an association with product #1
        $bugs = $repoBug->findFilteredByProduct(1);
         /* @var $bug 'Bug'Entity'Bug*/
        foreach ($bugs as $bug) {
            echo 'Bug #' . $bug->getBugId() . '<br/>';
            /* @var $p 'Bug'Entity'Product */
            foreach ($bug->getProduct() as $p) { // here only product #1 for all bugs available, thats fine
                echo '#' . $p->getProductId() . ' ' . $p->getName() . '<br/>';
            }
        }

        // get bug #1 with all associated products
        $bug1 = $repoBug->findWithProduct(1);
        $bug1 = reset($bug1);
        /* @var $p 'Bug'Entity'Product */
        foreach ($bug1->getProduct() as $p) { // here also only product #1 available, thats wrong, it should also product #2 available e.g. for bug #1
            echo '#' . $p->getProductId() . ' ' . $p->getName() . '<br/>';
        }
         // some other stuff
    }
}

执行的查询:

findFilteredByProduct(1):

SELECT
    b0_.bug_id AS bug_id0,
    b0_.description AS description1,
    b0_. STATUS AS status2,
    p1_.product_id AS product_id3,
    p1_. NAME AS name4
FROM
    bug b0_
INNER JOIN bug_product b2_ ON b0_.bug_id = b2_.bug_id
INNER JOIN product p1_ ON p1_.product_id = b2_.product_id
WHERE
    p1_.product_id = ?

findWithProduct(1):

SELECT
    b0_.bug_id AS bug_id0,
    b0_.description AS description1,
    b0_. STATUS AS status2,
    p1_.product_id AS product_id3,
    p1_. NAME AS name4
FROM
    bug b0_
INNER JOIN bug_product b2_ ON b0_.bug_id = b2_.bug_id
INNER JOIN product p1_ ON p1_.product_id = b2_.product_id
WHERE
    b0_.bug_id = ?

描述:

在第一个查询(findFilteredByProduct(1))中,我只得到一个产品id为1的bug实体。不使用延迟加载。如果我现在想得到所有相关产品的bug(findWithProduct(1)),它不起作用。bug实体有两个产品#1和#2,但实体管理器不会将第二个产品添加到之前检索到的bug实体中。

一种解决方案是在用第二个查询检索bug实体之前分离bug实体,但在一个巨大的应用程序中,我不知道这个实体以前是否已经存在,或者是否所有产品都可用。我认为这是一个独立于这个例子的常见用例,我不知道如何解决这个问题。我不想总是使用懒惰加载,例如为了性能。如果实体管理器将第二个产品添加到bug实体中,我可以使用集合的matching()函数只检索id为1的产品。

这是条令orm 2.3.4(也是2.4.0测试版)中的一个错误吗?如果不清除实体管理器或从第一个查询中分离bug实体,我该怎么办?

我从我的类型提示中看到还有一个leftJoin,所以我认为应该使用leftJoin()