php – Doctrine – Entity类中的Hydrate集合
我有关于双向OneToMany< - >的问题.我的实体Device和Event之间的ManyToOne关系.这是映射的外观:
// Device entity /** * @ORMOneToMany(targetEntity="AppBundleEntityEvent",mappedBy="device") */ protected $events; // Event entity /** * @ORMManyToOne(targetEntity="AppBundleEntityDevice",inversedBy="events") */ protected $device; 问题出现是因为Device是单表继承实体 * @ORMInheritanceType("SINGLE_TABLE") * @ORMDiscriminatorColumn(name="device_class_type",type="string") 每次我获取并迭代一些Event实体时,总是急切地获取$device.发生这种情况是因为它是relative documentation中报告的STI实体
现在有另一个名为Gateway的实体与Device和Event有关系: /** * @ORMOneToMany(targetEntity="AppBundleEntityDevice",mappedBy="gateway") */ protected $devices; /** * @ORMOneToMany(targetEntity="targetEntity="AppBundleEntityEvent",mappedBy="gateway") */ protected $events; public function getEvents(): Collection { return $this->events; } 当然,每当我遍历$gateway-> getEvents()时,所有相关事件设备都会被急切地获取.即使我没有获得任何$device信息,也会发生这种情况 – 一个空的foreach就足以让Doctrine为每个对象执行1个查询来获取相关的$device foreach ($gateway->getEvents() as $event) {} 现在我知道我可以使用QueryBuilder设置一个不同的水合模式,避免$device fetching return $this->getEntityManager()->createQueryBuilder() ->select('e') ->from('AppBundle:Event','e') ->where('e.gateway = :gateway') ->setParameter('gateway',$gateway) ->getQuery()->getResult(Query::HYDRATE_SIMPLEOBJECT); 但我想直接在Gateway实体中做到这一点. 那么可以直接在Gateway实体类中水合Gateway->事件吗?
你需要
write your own hydration method
您有一个循环引用,其中一个节点(Device)将强制FETCH EAGER.更糟糕的是,其中一个节点(Gateway)就像其他两个节点之间的ManyToMany连接表一样,导致FETCH EAGER在近无限循环(或至少大块相关数据)中加载所有内容. +──< OneToMany >──+ ManyToOne >──< ManyToMany +──+ OneToOne ┌──────< Gateway >──────┐ │ │ + + Event +──────────────< Device* 正如您所看到的,当设备执行EAGER提取时,它将收集许多网关,因此会收集许多事件,因此会有许多设备,因此会有更多网关等.获取EAGER将继续运行,直到填充所有引用. 通过建立自己的保湿器来防止“EAGER”保湿. 构建自己的保湿器需要一些仔细的数据操作,但对于您的用例可能会有些简单.记得用Doctrine注册您的保湿器,并将其作为参数传递给$query-> execute([],’GatewayHydrator’); class GatewayHydrator extends DefaultEntityHydrator { public function hydrateResultSet($stmt) { $data = $stmt->fetchAll(PDO::FETCH_ASSOC); $class = $this->em->getClassMetadata(Gateway::class); $gateway = $class->newInstance(); $gateway->setName($data[0]['gateway_name']); // example only return $gateway; } } 或者,从设备到网关删除映射字段 删除$gateway =>来自Device的网关映射和来自Gateway->设备映射的mappedBy =“gateway”,Device将从Doctrine的角度有效地成为一片叶子.这将避免该参考循环,但有一个缺点:必须手动设置Device-> gateway属性(可能在Gateway和Event setDevice方法中). (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |