7

我必须遵循设置:父类

/**
 * @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 表上连接)。相反,我得到一个主查询,然后是每个summand 的一个查询,每个查询都有一个大的胖序列LEFT JOIN文档也包含有关此问题的警告,我大量引用继承树的非叶节点)。

顺便说一句:LAZY获取已经足以避免加载 ManyToMany 吗?

这个评论中,我认为问题是我的子实体引用了父实体。我该如何规避这个?映射超类?

4

1 回答 1

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

之后,对于每个引用的 DataCategory 的许多 SELECT 查询就没有必要了,因为实体管理器已经看到了。

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

于 2018-10-11T12:01:25.597 回答