具有自引用的继承实体ManyToMany:EXTRA_LAZY获取模式不起作用

Oll*_*etz 7 doctrine lazy-loading class-table-inheritance

我必须遵循以下设置:父类

/**
 * @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;

    //...
}
Run Code Online (Sandbox Code Playgroud)

以及几个包含对父项的引用的派生类(仅显示一个)

/**
 * @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();
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,当通过加载所有MultiCompoundDataCategories时 $this->getDoctrine()->getRepository(MultiCompoundDataCategory::class)->findAll(),不仅会发出MultiCompoundDataCategories上的一个选择(在ManyToMany表上使用连接).相反,我得到一个主查询,然后是每个 summand 的一个查询,每个查询都有一个大的胖序列LEFT JOIN(文档包含有关此问题的警告,我正在大量引用继承树的非叶节点).

顺便说一句:LAZY提取不足以避免加载ManyToMany?

这个评论中,我认为问题是我的孩子实体拒绝了父母的实体.我怎么能绕过这个呢?MappedSuperclass?

Oll*_*etz 1

好吧,我发现了一些东西,但不知道是否有更好的解决方案。

这篇博文给了我解决方案的灵感(最后一段)。

通过执行 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();
Run Code Online (Sandbox Code Playgroud)

之后,不需要对每个引用的 DataCategory 进行许多 SELECT 查询,因为实体管理器已经看到了它。

这听起来很奇怪,但到目前为止,我的测试表明,具有大量水合工作负载的 4 个查询的运行速度比 ~800 个单选要快得多。