SQLAlchemy懒惰的声明性继承

时间:2012-10-30 13:25:51

标签: python orm sqlalchemy lazy-evaluation declarative

我们有几个表之间有声明性继承,我们一直在努力使继承“懒惰”,这意味着我们不想急切地在父表上加入。

例如:

class Entity(Base):
    __tablename__ = 'entities'
    id = Column(Integer, primary_key=True)
    entity_type = Column(String, nullable=False)
    __mapper_args__ = {'polymorphic_on': entity_type, 'polymorphic_identity': 'entities'}

class Person(Entity):
    __tablename__ = 'persons'
    person_id = Column(None, ForeignKey('entities.id'), primary_key=True)
    name = Column(String, nullable=False)
    __mapper_args__ = {'polymorphic_identity': 'persons'}

在查询Person时,sqlalchemy始终在实体上加入。我希望它有些懒惰,我找不到任何方法去做。

但是,在查询实体时,如果该实体是Person,我仍然希望能够接收Person对象。 这就是为什么我们不能简单地让Person与Entity建立关系或使用具有一个的Mixin。

1 个答案:

答案 0 :(得分:3)

此处的Person实体是Entity-> Person的连接。如果您只想查询“实体”表开头,则查询实体对象。如果您想要只有“Person”类型的Entity对象,则过滤鉴别器:

persons = query(Entity).filter_by(entity_type='persons').all()

上面将返回Person对象而不使用连接,并且当您访问Person特定属性时,将分别为每一行选择“persons”表。

编辑:好的,你想要反过来。首先,这是可能的,第二是我建议改变您的映射。

  1. 您总是可以通过查询表格从“人”中获取行:

    ptable = Person.__table__
    rows = query(ptable).filter(ptable.c.foo == 'bar').all()
    

    它为你提供了元组,而不是Person对象。

  2. 另一种可能有用的方法,虽然我没有尝试过,而且相当不寻常,就是对Person使用非主映射器:

    from sqlalchemy.orm import mapper
    nperson = mapper(Person, Person.__table__, non_primary=True)
    people = query(nperson).filter(nperson.c.foo == 'bar').all()
    
  3. 继承有利于Entity表的原因是因为在类继承中,Person被认为是Entity的特化 - 你得到的每个人实际上只是一个实体,具有一些额外的特性使其成为一个Person。 ORM将Person的主键视为“entities.id”列。这是因为所有Entity子类的空间跨越了许多表,但完整的Entity主键集仍然是“entities.id”中的那些值。 ORM还需要在此处查看“entities.entity_type”列,以查看对象的类型。如果“人员”加入了“员工”表并且你有class Employee(Person),那么只查询“人员”表不仅不会给我们记录的主键(将FK栏放在一边)而且还不会不区分人员和员工。

    从语义上讲,此处的使用请求可能表明继承不合适。假设实体有许多子类 - Person,Animal,Vehicle,并且每个子类都是子类表,它实际上是“记录数据”,而特定于Entity的列实际上只是关联值,这表明将关系建模为人与实体之间的一对一。 这种映射可以准确地获得您想要的加载行为;对Person的查询只针对“人”,访问Person.entity会发出一个SQL语句来获取相应的Entity。

  4. 另一个想法是,虽然我在这里看不到你的完整映射,但是如果“实体”实际上没有任何有意义的数据,除了作为“所有对象的基础”之外,恕我直言关于关系数据库的反模式。在Python中使用基类很好,但我绝对没有与之对应的数据库表,只会使查询和更新变得更加困难。

相关问题