继承层级中的叶子实体是什么?结合Doctrine STI/CTI场景求实例说明
什么是Doctrine继承映射中的叶子实体
单表继承(STI)或类表继承(CTI)存在一个通用性能注意事项:如果多对一或一对一关联的目标实体是STI或CTI实体,出于性能考虑,最好该实体是继承层级中的叶子实体(即没有子类)。否则Doctrine无法为该实体创建代理实例,始终会提前加载该实体。
在STI/CTI的实体继承树中,叶子实体指的是处于继承层级最末端、没有任何子类的实体,对应的非叶子实体就是存在子类的父类实体,包括抽象父类和有子类的普通实体类。
示例继承结构说明
你给出的实体继承关系如下:
- 顶层父类:
AbstractEngine(抽象类,共3个子类) - 子类1:
V8Engine(无其他子类) - 子类2:
V6Engine(无其他子类) - 子类3:
Straight4Engine(无其他子类)
在这个结构里,V8Engine、V6Engine、Straight4Engine都属于叶子实体,AbstractEngine属于非叶子实体。
关联目标为非叶子实体的示例
如果Automobile实体的关联指向父类AbstractEngine,代码示例如下:
/** * @Entity */ class Automobile { // 其他字段省略 /** * @ManyToOne(targetEntity=AbstractEngine::class) */ private $engine; }
这种场景下,因为AbstractEngine是非叶子实体,存在多个子类,Doctrine无法确定需要生成哪个子类的代理对象,所以每次查询Automobile的时候,都会立即执行额外的SQL查询加载关联的engine实体,无法使用懒加载,数据量较大时会产生明显的性能损耗。
关联目标为叶子实体的示例
如果业务中某类汽车固定使用V8引擎,就可以把关联指向叶子实体V8Engine,代码示例如下:
/** * @Entity */ class MuscleCar { // 其他字段省略 /** * @ManyToOne(targetEntity=V8Engine::class) */ private $engine; }
这种场景下,因为V8Engine是叶子实体,没有任何子类,Doctrine可以直接生成对应的代理对象,启用懒加载逻辑,只有当你实际调用$muscleCar->getEngine()的时候才会执行SQL查询加载引擎实体,大幅降低不必要的查询开销。
内容的提问来源于stack exchange,提问作者user1032531
相关产品推荐
相关产品推荐

