Доктрина 2 ManyToOne с несколькими объединенными столбцами

#mapping #left-join #doctrine-orm #many-to-one

#сопоставление #левое соединение #doctrine-orm #соотношение многих к одному

Вопрос:

Я пытаюсь выбрать соответствующую строку в таблице product_item_sortorder на основе ProductID и toolboxItemId из таблицы product_item.

В обычном SQL это было бы для данного ProductID:

 SELECT pi.*, pis.* FROM product_item pi
LEFT JOIN product_item_sortorder pis
    ON pi.productId = pis.productId
    AND pi.toolboxItemId = pis.toolboxItemId
WHERE pi.productId = 6
  

Я написал для него DQL следующим образом:

 $this->_em->createQuery(
    'SELECT pi
    FROM EntitiesProductItem pi
    LEFT JOIN pi.sequence s
    WHERE pi.product = ?1'
);
  

Затем я получаю следующий SQL, если я вывожу $query->getSQL():

 SELECT p0_.id AS id0, p0_.productId AS productId1, p0_.priceGroupId AS priceGroupId2, p0_.toolboxItemId AS toolboxItemId3, p0_.levelId AS levelId4, p0_.parentId AS parentId5, p0_.productId AS productId6, p0_.toolboxItemId AS toolboxItemId7 FROM product_item p0_ LEFT JOIN product_item_sortorder p1_ ON p0_.productId = p1_. AND p0_.toolboxItemId = p1_. WHERE p0_.productId = ? ORDER BY p0_.id ASC
  

Как вы можете видеть, указанные имена столбцов не найдены:

 LEFT JOIN product_item_sortorder p1_ ON p0_.productId = p1_. AND p0_.toolboxItemId = p1_. 
  

Подробная информация о таблице product_item:

  ----- ----------- --------------- 
| id  | productId | toolboxItemId |
 ----- ----------- --------------- 
| 467 |         1 |             3 |
| 468 |         1 |            10 |
| 469 |         1 |            20 |
| 470 |         1 |             4 |
| 471 |         1 |            10 |
 ----- ----------- --------------- 
  

Подробная информация о таблице product_item_sortorder:

  ----- ----------- --------------- ---------- 
| id  | productId | toolboxItemId | sequence |
 ----- ----------- --------------- ---------- 
| 452 |         1 |             3 |        1 |
| 457 |         1 |             4 |        6 |
| 474 |         1 |            20 |        4 |
 ----- ----------- --------------- ---------- 
  

Объект ProductItem

 <?php
/**
 * @Entity(repositoryClass="RepositoriesProductItem")
 * @Table(name="product_item")
 */
class ProductItem
{
    ...

    /**
     * @ManyToOne(targetEntity="ProductItemSortorder")
     * @JoinColumns({
     *      @JoinColumn(name="productId", referencedColumnName="productId"),
     *      @JoinColumn(name="toolboxItemId", referencedColumnName="toolboxItemId")
     * })
     */
    protected $sequence;

    ...
?>
  

Объект ProductItemSortOrder

 <?php
/**
 * @Entity(repositoryClass="RepositoriesProductItemSortorder")
 * @Table(name="product_item_sortorder")
 */
class ProductItemSortorder
{
    ...

    /**
     * @ManyToOne(targetEntity="Product")
     * @JoinColumn(name="productId", referencedColumnName="id")
     */
    protected $product;

    /**
     * @ManyToOne(targetEntity="ToolboxItem")
     * @JoinColumn(name="toolboxItemId", referencedColumnName="id")
     */
    protected $toolboxItem;

    ...
}
?>
  

Ответ №1:

Ваши сопоставления серьезно неверны. Вы используете ManyToOne на обоих концах, как это возможно? У вас обе ассоциации определены как на стороне «владельца», без сопоставления или инверсии (см. Главу «Сопоставления ассоциаций»). И вы используете столбцы объединения одной ассоциации для сопоставления со многими полями в другом объекте. Я полагаю, вы хотите сделать что-то еще, можете ли вы точно описать свой вариант использования?

Комментарии:

1. Я немного обновил вопрос, и ниже вы можете увидеть, какой запрос я хочу выполнить

Ответ №2:

Как бы вы сопоставили свой пример в YAML (поскольку пример @Hernan Rajchert представлен только в аннотациях):

 ProductItem:
    type: entity

    manyToOne:
        sequence:
            targetEntity: ProductItemSortorder
            joinColumns:
                productId:
                    referencedColumnName: productId
                toolboxItemId:
                    referencedColumnName: toolboxItemId