正在加载继承层次结构
当使用“joined”、“single”或“concrete”表继承样式在继承层次结构中映射类时,如中所述 映射类继承层次结构 通常的行为是,对特定基类的查询也将生成与子类相对应的对象。当单个查询能够返回每个结果行具有不同类或子类的结果时,我们使用术语“多态加载”。
在多态加载领域,特别是联合表继承和单表继承,还有一个额外的问题,子类属性需要预先查询,然后再加载。当预先查询某个特定子类的属性时,我们可以在查询中使用它作为要过滤的对象,当我们取回对象时,它也将被加载。如果它不是预先查询的,那么当我们第一次需要访问它时,它会在稍后加载。此行为的基本控制是使用 with_polymorphic()
函数,以及两个变量,映射器配置 mapper.with_polymorphic
与 mapper.polymorphic_load
选项,以及 Query
水平 Query.with_polymorphic()
方法。“with_多态”系列每个都提供了一种方法,用于指定在查询中应包括特定基类的哪些特定子类,这意味着选择中可以使用哪些列和表。
与多态性一起使用
对于以下部分,假设 Employee
/ Engineer
/ Manager
示例介绍于 映射类继承层次结构 .
通常,当 Query
指定继承层次结构的基类,仅查询该基类的本地列::
session.query(Employee).all()
上面,对于单表继承和联接表继承,只有本地列 Employee
将出现在选择中。我们可以取回 Engineer
或 Manager
但是,在我们第一次访问它们之前,它们不会加载其他属性,此时将发出一个延迟加载。
同样,如果我们想引用映射到 Engineer
或 Manager
在我们的质询中 Employee
,这些列在单表继承或联接表继承情况下都不直接可用,因为 Employee
实体不引用这些列(请注意,对于单表继承,如果使用声明性的,这是很常见的,但对于经典映射则不常见)。
为了解决这两个问题, with_polymorphic()
函数提供一个特殊的 AliasedClass
它表示跨子类的一系列列。此对象可用于 Query
像其他别名一样。查询时,它表示给定类中存在的所有列:
from sqlalchemy.orm import with_polymorphic eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager]) query = session.query(eng_plus_manager)
如果上面的映射使用联接表继承,上面的select语句将是:
query.all() SELECT employee.id AS employee_id, engineer.id AS engineer_id, manager.id AS manager_id, employee.name AS employee_name, employee.type AS employee_type, engineer.engineer_info AS engineer_engineer_info, manager.manager_data AS manager_manager_data FROM employee LEFT OUTER JOIN engineer ON employee.id = engineer.id LEFT OUTER JOIN manager ON employee.id = manager.id []
在上面的位置,包括“工程师”和“经理”的附加表/列。在单表继承的情况下也会发生类似的行为。
with_polymorphic()
接受单个类或映射器、类/映射器列表或字符串 '*'
要指示所有子类:
# include columns for Engineer entity = with_polymorphic(Employee, Engineer) # include columns for Engineer, Manager entity = with_polymorphic(Employee, [Engineer, Manager]) # include columns for all mapped subclasses entity = with_polymorphic(Employee, '*')
小技巧
值得注意的是, with_polymorphic()
仅影响 读取的行中包含的列 ,而不是 返回的对象类型 。打电话给 with_polymorphic(Employee, [Manager])
将引用包含所有类型的 Employee
对象,不仅包括 Manager
对象,但也 Engineer
对象,因为这些对象是 Employee
,以及 Employee
实例(如果数据库中存在这些实例)。使用的效果 with_polymorphic(Employee, [Manager])
仅提供特定于以下内容的附加列的行为 Manager
将被急切地加载到结果行中,如下所述 引用特定的子类属性 也可在SELECT语句的WHERE子句中使用。
将混叠与多态性一起使用
这个 with_polymorphic()
函数还提供多态选择本身的“混叠”,也就是说,两个不同的 with_polymorphic()
引用同一类层次结构的实体可以一起使用。可以使用 with_polymorphic.aliased
旗子。对于跨多个表的多态可选项,默认行为是将可选项包装到子查询中。下面我们将发出一个查询,该查询将选择“employee or manager”与“employee or engineer”对同名员工:
engineer_employee = with_polymorphic( Employee, [Engineer], aliased=True) manager_employee = with_polymorphic( Employee, [Manager], aliased=True) q = s.query(engineer_employee, manager_employee).\ join( manager_employee, and_( engineer_employee.id > manager_employee.id, engineer_employee.name == manager_employee.name ) ) q.all() SELECT anon_1.employee_id AS anon_1_employee_id, anon_1.employee_name AS anon_1_employee_name, anon_1.employee_type AS anon_1_employee_type, anon_1.engineer_id AS anon_1_engineer_id, anon_1.engineer_engineer_name AS anon_1_engineer_engineer_name, anon_2.employee_id AS anon_2_employee_id, anon_2.employee_name AS anon_2_employee_name, anon_2.employee_type AS anon_2_employee_type, anon_2.manager_id AS anon_2_manager_id, anon_2.manager_manager_name AS anon_2_manager_manager_name FROM ( SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type, engineer.id AS engineer_id, engineer.engineer_name AS engineer_engineer_name FROM employee LEFT OUTER JOIN engineer ON employee.id = engineer.id ) AS anon_1 JOIN ( SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type, manager.id AS manager_id, manager.manager_name AS manager_manager_name FROM employee LEFT OUTER JOIN manager ON employee.id = manager.id ) AS anon_2 ON anon_1.employee_id > anon_2.employee_id AND anon_1.employee_name = anon_2.employee_name
上面的子查询的创建非常冗长。虽然它创建了两个不同查询的最佳封装,但可能效率低下。 with_polymorphic()
包括一个额外的标志来帮助处理这种情况, with_polymorphic.flat
它将把子查询/联接组合“展平”为直接联接,而对单个表应用别名。设置 with_polymorphic.flat
暗示 with_polymorphic.aliased
,因此只需要一个标志:
engineer_employee = with_polymorphic( Employee, [Engineer], flat=True) manager_employee = with_polymorphic( Employee, [Manager], flat=True) q = s.query(engineer_employee, manager_employee).\ join( manager_employee, and_( engineer_employee.id > manager_employee.id, engineer_employee.name == manager_employee.name ) ) q.all() SELECT employee_1.id AS employee_1_id, employee_1.name AS employee_1_name, employee_1.type AS employee_1_type, engineer_1.id AS engineer_1_id, engineer_1.engineer_name AS engineer_1_engineer_name, employee_2.id AS employee_2_id, employee_2.name AS employee_2_name, employee_2.type AS employee_2_type, manager_1.id AS manager_1_id, manager_1.manager_name AS manager_1_manager_name FROM employee AS employee_1 LEFT OUTER JOIN engineer AS engineer_1 ON employee_1.id = engineer_1.id JOIN ( employee AS employee_2 LEFT OUTER JOIN manager AS manager_1 ON employee_2.id = manager_1.id ) ON employee_1.id > employee_2.id AND employee_1.name = employee_2.name
使用时,请注意上述内容 with_polymorphic.flat
,当与联接表继承结合使用时,通常情况下,我们在语句中得到一个正确的嵌套联接。一些较旧的数据库,特别是较旧版本的sqlite,可能会遇到这种语法问题,尽管现在几乎所有现代数据库版本都支持这种语法。
注解
这个 with_polymorphic.flat
标志仅适用于 with_polymorphic
具有 联接表继承 当 with_polymorphic.selectable
论证是 not 使用。
引用特定的子类属性
返回的实体 with_polymorphic()
是一个 AliasedClass
对象,可以在 Query
和其他别名一样,包括 Employee
班级。在前面的示例中, eng_plus_manager
成为我们用来引用上面的三向外部联接的实体。它还包括类列表中命名的每个类的名称空间,以便也可以调用这些子类的特定属性。下面的示例说明调用特定于 Engineer
以及 Manager
依据 eng_plus_manager
::
eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager]) query = session.query(eng_plus_manager).filter( or_( eng_plus_manager.Engineer.engineer_info=='x', eng_plus_manager.Manager.manager_data=='y' ) )
如上所述的查询将生成如下所示的SQL:
query.all() SELECT employee.id AS employee_id, engineer.id AS engineer_id, manager.id AS manager_id, employee.name AS employee_name, employee.type AS employee_type, engineer.engineer_info AS engineer_engineer_info, manager.manager_data AS manager_manager_data FROM employee LEFT OUTER JOIN engineer ON employee.id = engineer.id LEFT OUTER JOIN manager ON employee.id = manager.id WHERE engineer.engineer_info=? OR manager.manager_data=? ['x', 'y']
在映射器配置时使用多态性设置
这个 with_polymorphic()
函数的作用是允许从子类表中“急”加载属性,以及在查询时引用子类表中的属性。从历史上看,柱的“急加载”是方程式中更重要的部分。因此,正如对关系的渴望加载可以被指定为配置选项一样, mapper.with_polymorphic
默认情况下,配置参数允许实体使用多态加载。我们可以将参数添加到 Employee
首次引入映射于 联接表继承 ::
class Employee(Base): __tablename__ = 'employee' id = Column(Integer, primary_key=True) name = Column(String(50)) type = Column(String(50)) __mapper_args__ = { 'polymorphic_identity':'employee', 'polymorphic_on':type, 'with_polymorphic': '*' }
上面是一个常见的设置 mapper.with_polymorphic
,表示要加载所有子类列的星号。在联接表继承的情况下,应谨慎使用此选项,因为它意味着映射将始终向多个表发出一系列(通常是大的)左外部联接,从SQL的角度来看,这是不高效的。对于单表继承,指定星号通常是一个好主意,因为加载仍然只针对一个表,但是会阻止子类映射列的额外延迟加载。
使用 with_polymorphic()
或 Query.with_polymorphic()
将覆盖映射器级别 mapper.with_polymorphic
设置。
这个 mapper.with_polymorphic
选项还接受类列表,就像 with_polymorphic()
在类的子集中以多态方式加载。但是,在使用声明性的时候,不能直接向这个列表提供类,因为我们要添加的子类还不可用。相反,我们可以在每个子类上指定,默认情况下,它们应该单独参与多态加载,使用 mapper.polymorphic_load
参数::
class Engineer(Employee): __tablename__ = 'engineer' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) engineer_info = Column(String(50)) __mapper_args__ = { 'polymorphic_identity':'engineer', 'polymorphic_load': 'inline' } class Manager(Employee): __tablename__ = 'manager' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) manager_data = Column(String(50)) __mapper_args__ = { 'polymorphic_identity':'manager', 'polymorphic_load': 'inline' }
设置 mapper.polymorphic_load
值的参数 "inline"
意味着 Engineer
和 Manager
上面的类是基础的“多态负载”的一部分 Employee
默认情况下,就像它们被附加到 mapper.with_polymorphic
课程列表。
对查询使用多态性设置
这个 with_polymorphic()
从查询级别方法演变而来的函数 Query.with_polymorphic()
. 此方法的目的与 with_polymorphic()
,但它的使用模式没有那么灵活,因为它只适用于 Query
. 然后,它对该实体的所有出现都生效,这样就可以直接引用该实体(及其子类),而不是使用别名对象。对于简单的情况,可以认为更简洁:
session.query(Employee).\ with_polymorphic([Engineer, Manager]).\ filter( or_( Engineer.engineer_info=='w', Manager.manager_data=='q' ) )
这个 Query.with_polymorphic()
方法的工作比 with_polymorphic()
函数,因为它需要正确地转换 Engineer
和 Manager
适当,但不干扰其他实体。如果缺少灵活性,请切换到使用 with_polymorphic()
.
多态性选择素加载
替代使用 with_polymorphic()
在继承映射上“急切地”加载附加子类的函数家族,主要是在使用联合表继承时,将使用多态的“selectin”加载。这是一个紧急加载功能,其工作原理与 加载时选择 关系加载的功能。对于我们的示例映射,我们可以指示 Employee
通过使用 selectin_polymorphic()
加载器选项:
from sqlalchemy.orm import selectin_polymorphic query = session.query(Employee).options( selectin_polymorphic(Employee, [Manager, Engineer]) )
当运行上述查询时,将发出两条附加的select语句:
query.all() SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type FROM employee () SELECT engineer.id AS engineer_id, employee.id AS employee_id, employee.type AS employee_type, engineer.engineer_name AS engineer_engineer_name FROM employee JOIN engineer ON employee.id = engineer.id WHERE employee.id IN (?, ?) ORDER BY employee.id (1, 2) SELECT manager.id AS manager_id, employee.id AS employee_id, employee.type AS employee_type, manager.manager_name AS manager_manager_name FROM employee JOIN manager ON employee.id = manager.id WHERE employee.id IN (?) ORDER BY employee.id (3,)
我们也可以通过指定 mapper.polymorphic_load
参数,使用值 "selectin"
根据子类:
class Employee(Base): __tablename__ = 'employee' id = Column(Integer, primary_key=True) name = Column(String(50)) type = Column(String(50)) __mapper_args__ = { 'polymorphic_identity': 'employee', 'polymorphic_on': type } class Engineer(Employee): __tablename__ = 'engineer' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) engineer_name = Column(String(30)) __mapper_args__ = { 'polymorphic_load': 'selectin', 'polymorphic_identity': 'engineer', } class Manager(Employee): __tablename__ = 'manager' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) manager_name = Column(String(30)) __mapper_args__ = { 'polymorphic_load': 'selectin', 'polymorphic_identity': 'manager', }
与使用时不同 with_polymorphic()
,当使用 selectin_polymorphic()
装载方式,我们有 not 有能力参考 Engineer
或 Manager
主查询中的实体作为筛选、排序依据或其他条件,因为这些实体在用于定位结果的初始查询中不存在。但是,我们可以应用应用于 Engineer
或 Manager
,在发出次选择时生效。下面我们假设 Manager
有额外的关系 Manager.paperwork
,我们也很乐意装载。我们可以使用任何类型的预加载,例如通过 joinedload()
功能:
from sqlalchemy.orm import joinedload from sqlalchemy.orm import selectin_polymorphic query = session.query(Employee).options( selectin_polymorphic(Employee, [Manager, Engineer]), joinedload(Manager.paperwork) )
使用上面的查询,我们得到三个发出的select语句,但是其中一个针对 Manager
将:
SELECT manager.id AS manager_id, employee.id AS employee_id, employee.type AS employee_type, manager.manager_name AS manager_manager_name, paperwork_1.id AS paperwork_1_id, paperwork_1.manager_id AS paperwork_1_manager_id, paperwork_1.data AS paperwork_1_data FROM employee JOIN manager ON employee.id = manager.id LEFT OUTER JOIN paperwork AS paperwork_1 ON manager.id = paperwork_1.manager_id WHERE employee.id IN (?) ORDER BY employee.id (3,)
注意,selectin多态加载与selectin关系加载有类似的注意事项;对于使用复合主键的实体,使用中的数据库必须支持tuples with“in”,目前已知该tuples可用于mysql和postgresql。
1.2 新版功能.
警告
选择素多态性加载特征应被视为 实验的 在1.2系列的早期版本中。
选择素与多态性结合
注解
自1.2.0b3起工作
经过仔细规划,selectin加载可以应用于自身使用“with_多态性”的层次结构。一个特殊的用例是使用selectin加载来加载一个连接的继承子表,然后使用“with_多态性”来引用更多的子类,这些子类可以是连接的或单表继承。如果我们添加了一个类 VicePresident
延伸的 Manager
使用单表继承,我们可以确保 Manager
同时满载 VicePresident
同时的子类型:
# use "Employee" example from the enclosing section class Manager(Employee): __tablename__ = 'manager' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) manager_name = Column(String(30)) __mapper_args__ = { 'polymorphic_load': 'selectin', 'polymorphic_identity': 'manager', } class VicePresident(Manager): vp_info = Column(String(30)) __mapper_args__ = { "polymorphic_load": "inline", "polymorphic_identity": "vp" }
以上,我们添加了 vp_info
列到 manager
表,本地 VicePresident
子类。这个子类与多态性身份有关。 "vp"
它指的是具有此数据的行。通过将加载样式设置为“inline”,这意味着 Manager
对象还将确保 vp_info
在同一个select语句中查询列。对…的质疑 Employee
遇到一个 Manager
行将发出类似于以下内容的内容:
SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type FROM employee ) SELECT manager.id AS manager_id, employee.id AS employee_id, employee.type AS employee_type, manager.manager_name AS manager_manager_name, manager.vp_info AS manager_vp_info FROM employee JOIN manager ON employee.id = manager.id WHERE employee.id IN (?) ORDER BY employee.id (1,)
结合“selectin”多态加载和查询时间 with_polymorphic()
也可以使用(尽管这是非常外层空间的东西!);假设上述映射没有 polymorphic_load
设置,我们可以得到如下相同的结果:
from sqlalchemy.orm import with_polymorphic, selectin_polymorphic manager_poly = with_polymorphic(Manager, [VicePresident]) s.query(Employee).options( selectin_polymorphic(Employee, [manager_poly])).all()
在关系中引用特定的子类型
对应于 relationship()
用于查询以引用两个映射之间的链接。常用的用法是指 relationship()
在里面 Query.join()
以及加载程序选项,如 joinedload()
. 使用时 relationship()
如果目标类是继承层次结构,则API允许联接、预加载或其他链接以特定的子类、别名或 with_polymorphic()
该类层次结构的别名,而不是 relationship()
.
这个 of_type()
方法允许沿着 relationship()
将条件缩小到特定派生别名或子类时的路径。假设 employees
表表示与 Company
对象。我们将添加一个 company_id
列到 employees
桌子和新桌子 companies
:
class Company(Base): __tablename__ = 'company' id = Column(Integer, primary_key=True) name = Column(String(50)) employees = relationship("Employee", backref='company') class Employee(Base): __tablename__ = 'employee' id = Column(Integer, primary_key=True) type = Column(String(20)) company_id = Column(Integer, ForeignKey('company.id')) __mapper_args__ = { 'polymorphic_on':type, 'polymorphic_identity':'employee', } class Engineer(Employee): __tablename__ = 'engineer' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) engineer_info = Column(String(50)) __mapper_args__ = {'polymorphic_identity':'engineer'} class Manager(Employee): __tablename__ = 'manager' id = Column(Integer, ForeignKey('employee.id'), primary_key=True) manager_data = Column(String(50)) __mapper_args__ = {'polymorphic_identity':'manager'}
从查询时 Company
上 Employee
关系 Query.join()
方法和运算符 PropComparator.any()
和 PropComparator.has()
将从创建联接 company
到 employee
,不包括 engineer
或 manager
在混合中。如果我们希望有一个特别反对 Engineer
类,我们可以告诉这些方法使用 PropComparator.of_type()
操作员:
session.query(Company).\ join(Company.employees.of_type(Engineer)).\ filter(Engineer.engineer_info=='someinfo')
同样,从 Company
到包含两个元素的多态实体 Engineer
和 Manager
柱::
manager_and_engineer = with_polymorphic( Employee, [Manager, Engineer]) session.query(Company).\ join(Company.employees.of_type(manager_and_engineer)).\ filter( or_( manager_and_engineer.Engineer.engineer_info == 'someinfo', manager_and_engineer.Manager.manager_data == 'somedata' ) )
这个 PropComparator.any()
和 PropComparator.has()
操作员也可以与 of_type()
例如,当嵌入的条件是子类时:
session.query(Company).\ filter( Company.employees.of_type(Engineer). any(Engineer.engineer_info=='someinfo') ).all()
特异性或多态性亚型的热切加载
这个 joinedload()
, subqueryload()
, contains_eager()
和其他热切装载机选项支持使用 of_type()
. 下面,我们载入 Company
行,同时加载相关的 Engineer
对象,查询 employee
和 engineer
同时表格:
session.query(Company).\ options( subqueryload(Company.employees.of_type(Engineer)). subqueryload(Engineer.machines) ) )
情况也是如此 Query.join()
, PropComparator.of_type()
可用于将预加载和 with_polymorphic()
,以便可以加载所有引用子类型的所有子属性::
manager_and_engineer = with_polymorphic( Employee, [Manager, Engineer], flat=True) session.query(Company).\ options( joinedload( Company.employees.of_type(manager_and_engineer) ) )
注解
使用时 with_polymorphic()
与 joinedload()
, the with_polymorphic()
对象必须与“别名”对象相对,该对象是 Alias
,以便对多态可选对象进行别名处理(否则将引发信息性错误消息)。
典型的方法是包括 with_polymorphic.aliased
或 flat
标志,它将自动应用此别名。但是,如果 with_polymorphic.selectable
参数正用于传递已经是 Alias
对象,则此标志应 not 被设定。“flat”选项意味着“aliased”选项,它是针对产生较少子查询的联接对象的别名的另一种形式。
一次 PropComparator.of_type()
是渴望加载的目标,这是我们将用于后续链接的实体,而不是原始类或派生类。如果我们想进一步将一个集合加载到 Engineer
类,我们从 with_polymorphic()
对象:
session.query(Company).\ options( joinedload(Company.employees.of_type(manager_and_engineer)).\ subqueryload(manager_and_engineer.Engineer.computers) ) )
正在加载具有联接表继承的对象
当使用联接表继承时,如果我们查询表示两个表(如 Engineer
继承部分的示例中,发出的SQL是一个联接::
session.query(Engineer).all()
上面的查询将发出类似SQL的信息:
SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type, engineer.name AS engineer_name FROM employee JOIN engineer ON employee.id = engineer.id
然后我们会收集 Engineer
对象返回,其中将包含来自 employee
和 engineer
加载。
但是,当发出 Query
对于基类,行为仅从基表加载::
session.query(Employee).all()
在上面,默认行为将是仅从 employee
表而不是任何“子”表 (engineer
和 manager
,在前面的示例中):
SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type FROM employee []
在收集 Employee
对象已从查询中返回,因为属性是从这些查询中请求的 Employee
对象,在 engineer
或 manager
子表,如果尚未加载数据,则为该相关行中的列发出第二次加载。因此,在访问对象之后,您将看到沿着以下行发布的更多SQL:
SELECT manager.id AS manager_id, manager.manager_data AS manager_manager_data FROM manager WHERE ? = manager.id [5] SELECT engineer.id AS engineer_id, engineer.engineer_info AS engineer_engineer_info FROM engineer WHERE ? = engineer.id [2]
这个 with_polymorphic()
函数和相关的配置选项允许我们发出一个预先连接,它将根据 employee
, engineer
或 manager
,非常类似于joined-eager-loading为关系工作,消除了每个实体加载一秒钟的必要性:
from sqlalchemy.orm import with_polymorphic eng_plus_manager = with_polymorphic(Employee, [Engineer, Manager]) query = session.query(eng_plus_manager)
上面生成的查询将 employee
两人的桌子 engineer
和 manager
如下表格:
query.all() SELECT employee.id AS employee_id, engineer.id AS engineer_id, manager.id AS manager_id, employee.name AS employee_name, employee.type AS employee_type, engineer.engineer_info AS engineer_engineer_info, manager.manager_data AS manager_manager_data FROM employee LEFT OUTER JOIN engineer ON employee.id = engineer.id LEFT OUTER JOIN manager ON employee.id = manager.id []
断面 与多态性一起使用 讨论 with_polymorphic()
函数及其构型变体。
参见
加载具有单表继承的对象
在现代的声明式中,单继承映射产生 Column
对象只映射到一个子类,而不从超类中可用,即使它们存在于同一个表中。在我们的示例中, 单表继承 , the Manager
例如,映射具有 Column
明确规定::
class Manager(Employee): manager_data = Column(String(50)) __mapper_args__ = { 'polymorphic_identity':'manager' }
上面没有 Employee.manager_data
属性,即使 employee
表有 manager_data
列。对…的质疑 Manager
将在查询中包含此列,以及只将行限制为的In子句 Manager
物体:
session.query(Manager).all() SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type, employee.manager_data AS employee_manager_data FROM employee WHERE employee.type IN (?) ('manager',)
但是,以与联接表继承类似的方式,查询 Employee
将只查询映射到的列 Employee
:
session.query(Employee).all() SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type FROM employee
如果我们得到一个 Manager
根据我们的结果,访问附加的列只映射到 Manager
以类似于联接继承的方式为这些列发出延迟加载:
SELECT employee.manager_data AS employee_manager_data FROM employee WHERE employee.id = ? AND employee.type IN (?)
这个 with_polymorphic()
在单继承的情况下,函数的作用类似于联合继承;它既允许预先加载子类属性,也允许在查询中指定子类,而不需要使用外部联接的开销:
employee_poly = with_polymorphic(Employee, '*') q = session.query(employee_poly).filter( or_( employee_poly.name == 'a', employee_poly.Manager.manager_data == 'b' ) )
上面,我们的查询仍然针对单个表,但是我们可以引用 Manager
或 Engineer
使用“多态”名称空间。因为我们指定了 "*"
对于实体,两者都是 Engineer
和 Manager
将立即加载。发出的SQL将是:
q.all() SELECT employee.id AS employee_id, employee.name AS employee_name, employee.type AS employee_type, employee.manager_data AS employee_manager_data, employee.engineer_info AS employee_engineer_info FROM employee WHERE employee.name = :name_1 OR employee.manager_data = :manager_data_1
继承加载API
Object Name | Description |
---|---|
selectin_polymorphic(base_cls, classes) | 指示应为特定于子类的所有属性执行一个紧急加载。 |
with_polymorphic(base, classes[, selectable, flat, ...]) | 产生一个 |
- function sqlalchemy.orm.with_polymorphic(base, classes, selectable=False, flat=False, polymorphic_on=None, aliased=False, innerjoin=False, _use_mapper_path=False, _existing_alias=None)¶
产生一个
AliasedClass
为给定基的后代映射器指定列的构造。使用此方法将确保每个子代映射器的表都包含在FROM子句中,并允许对这些表使用filter()条件。结果实例还将加载这些列,这样就不需要对这些列进行“后提取”。
参见
与多态性一起使用 -充分讨论
with_polymorphic()
.- 参数
base¶ -- 要别名的基类。
classes¶ -- 从基类继承的单个类或映射器或类/映射器列表。或者,它也可以是字符串
'*'
在这种情况下,所有降序映射类都将添加到FROM子句中。aliased¶ -- 如果为True,则可选择项将具有别名。对于联接,这意味着将从子查询内部选择联接,除非
with_polymorphic.flat
flag设置为True,对于更简单的用例,建议这样做。flat¶ -- 布尔值,将传递给
FromClause.alias()
调用以便Join
对象将对联接内的各个表进行别名,而不是创建子查询。对于右嵌套联接,这通常由所有现代数据库支持,并且通常生成更高效的查询。只要生成的SQL正常工作,就建议设置此标志。selectable¶ -- 一种表或子查询,它将用来代替生成自子句。如果任何所需类使用具体的表继承,则需要此参数,因为SQLAlchemy当前无法在表之间自动生成联合。如果使用,则
selectable
参数必须表示由每个映射类映射的完整表和列集。否则,未计数的映射列将导致其表直接附加到FROM子句,这通常会导致错误的结果。polymorphic_on¶ -- 要用作给定可选项的“鉴别器”列的列。如果没有给出,将使用基类映射器的多态性属性(如果有的话)。这对于默认情况下没有多态加载行为的映射很有用。
innerjoin¶ -- 如果为true,则将使用内部联接。只有在仅查询一个特定子类型时才应指定此项
- function sqlalchemy.orm.selectin_polymorphic(base_cls, classes)¶
指示应为特定于子类的所有属性执行一个紧急加载。
这将对所有匹配的主键值使用一个带有in的附加select,并且每个查询类似于
"selectin"
设置在mapper.polymorphic_load
参数。1.2 新版功能.
参见