2013-08-25 2 views
0

У меня есть DB/Entity Structure. Таким образом, ошибка может иметь несколько продуктов. Я не получаю ожидаемое поведение в скрипте, если я использую разные запросы (другое условие соединения). Надеюсь, его легче понять с помощью следующего примера кода.Администратор сущности не ожидал поведения с отношениями (разные запросы)

Подготовка базы данных:

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); 

Repository:

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)), я получаю объекты ошибок только с одним продуктом, у которого есть идентификатор продукта 1. Никакая ленивая загрузка не используется. Если я хочу сейчас получить ошибку со всеми связанными продуктами (findWithProduct (1)), она не работает. Объект ошибки имеет, например, два продукта # 1 и # 2, но диспетчер объектов не добавляет второй продукт в объект ошибки, который был ранее извлечен.

Одним из решений является отделить объект ошибки до получения их вторым запросом, но в огромном приложении, я не знаю, существует ли объект до или если все продукты доступны. Я думаю, что это обычный случай использования, не зависящий от этого примера, и я не знаю, как решить эту проблему. Я не хочу всегда использовать ленивую загрузку, например. для производительности. Если менеджер объектов добавит второй продукт в объект ошибки, я мог бы использовать функцию соответствия() коллекции, чтобы получить только продукт с идентификатором 1.

Это ошибка в доктрине orm 2.3.4 (также 2.4.0 бета)? Что я могу сделать без очистки диспетчера сущностей или отделить объект ошибки от первого запроса?

ответ

0

Я вижу из своих типов подсказок, что есть также leftJoin, поэтому я думаю, что вы должны использовать вместо этого leftJoin().

Смежные вопросы