Унаследованная сущность с самоссылкой ManyToMany: режим извлечения EXTRA_LAZY не работает - PullRequest
0 голосов
/ 07 октября 2018

Мне нужно выполнить следующие настройки: родительский класс

/**
 * @ORM\Entity()
 * @ORM\InheritanceType("JOINED")
 * @ORM\DiscriminatorColumn(name="discr", type="string")
 */
abstract class DataCategory
{
    /**
     * @ORM\Column(name="id", type="integer")
     * @ORM\Id
     * @ORM\GeneratedValue(strategy="AUTO")
     */
    protected $id;

    //...
}

и несколько производных классов, которые содержат ссылки на родительский класс (только здесь показан один)

/**
 * @ORM\Entity
 */
class MultiCompoundDataCategory extends DataCategory
{
    /**
     * @ORM\ManyToMany(targetEntity="DataCategory", fetch="EXTRA_LAZY")
     * @ORM\JoinTable(name="multi_compound_data_category_data_category",
     *      joinColumns={@ORM\JoinColumn(name="multi_compound_data_category", referencedColumnName="id")},
     *      inverseJoinColumns={@ORM\JoinColumn(name="data_category", referencedColumnName="id")})
     */
    public $summands;


    public function __construct()
    {
        $this->summands = new ArrayCollection();
    }
}

Теперь при загрузке всехMultiCompoundDataCategories через $this->getDoctrine()->getRepository(MultiCompoundDataCategory::class)->findAll(), выдается не только один выбор для MultiCompoundDataCategories (с объединением в таблице ManyToMany).Вместо этого я получаю один основной запрос, за которым следует один запрос для каждого слагаемого, каждое с большой жирной последовательностью LEFT JOIN (также документы содержат предупреждение об этой проблеме, я в массовом порядкессылка на неконечные узлы дерева наследования).

Кстати: не будет LAZY выборки уже достаточной, чтобы избежать загрузки ManyToMany?

Из этого комментария ,Я предполагаю, что проблема в том, что мои дочерние сущности защищают родительскую сущность.Как я могу обойти это?MappedSuperclass

1 Ответ

0 голосов
/ 11 октября 2018

Хорошо, я нашел что-то, но не знаю, существует ли лучшее решение.

Эта запись в блоге дала мне подсказку к решению (последний абзац).

Выполнив соединение извлечения DQL, я могу быстро загрузить дочернюю сущность гидратированными ссылками.Поэтому я загружаю все дочерние классы.

$all=[];
$all['sampled'] = $em->createQuery("SELECT s FROM ".SampledDataCategory::class." s")->getResult();
$all['compound'] = $em->createQuery("SELECT c, s, s2 FROM ".CompoundDataCategory::class." c JOIN c.cat1 s JOIN c.cat2 s2")->getResult();
$all['unary'] = $em->createQuery("SELECT u, s FROM ".UnaryDataCategory::class." u JOIN u.dataCategory s")->getResult();
$all['multi'] = $em->createQuery("SELECT m, s FROM ".MultiCompoundDataCategory::class." m JOIN m.summands s")->getResult();

После этого многие запросы SELECT для каждой отдельной ссылочной DataCategory не нужны, потому что менеджер сущностей уже видел это.

Это звучит странно, но до сих пор мои тестыуказывают на то, что 4 запроса с большой рабочей нагрузкой на гидратацию выполняются намного быстрее, чем ~ 800 отдельных выборок.

...