1

宣言型の継承を持つテーブルがいくつかあり、継承を「レイジー」にしようとしています。つまり、親テーブルに熱心に参加したくないということです。

例えば:

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は常にEntityに参加します。私はそれをどういうわけか怠惰にしたいと思います、そして私はそれをする方法を見つけることができませんでした。

ただし、エンティティにクエリを実行する場合でも、そのエンティティがPersonである場合は、Personオブジェクトを受信できるようにしたいと思います。そのため、PersonにEntityとの関係を持たせたり、Mixinを使用したりすることはできません。

4

1 に答える 1

3

ここでのPersonエンティティは、Entity->Personの結合です。最初に「entities」テーブルをクエリするだけの場合は、Entityオブジェクトをクエリします。タイプが「Person」のみのエンティティオブジェクトが必要な場合は、識別子でフィルタリングします。

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

上記は、結合を使用せずにPersonオブジェクトを返します。また、Person固有の属性にアクセスすると、「persons」テーブルが各行に対して個別に選択されます。

編集:わかりました、あなたはそれを逆にしたいです。まず、それがどのように可能になるかを説明します。次に、マッピングを変更することをお勧めします。

  1. テーブルに対してクエリを実行することで、いつでも「person」から行を取り戻すことができます。

    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は、実際には単なるEntityであり、Personになるいくつかの追加の品質があります。ORMは、Personの主キーを「entities.id」列と見なします。これは、すべてのエンティティサブクラスのスペースが多くのテーブルにまたがっているが、エンティティの主キーの完全なセットが「entities.id」の値のままであるためです。ORMは、オブジェクトのタイプを確認するために、ここで「entities.entity_type」列も確認する必要があります。「persons」がテーブル「employees」に参加していてclass Employee(Person)、「persons」テーブルのみをクエリすると、レコードの主キー(personsのFK列は別として)が得られるだけでなく、

    意味的には、ここでの使用要求は、継承が適切でないことを示唆している可能性があります。エンティティに多くのサブクラス(Person、Animal、Vehicle)があり、それぞれについて実際に「レコードのデータ」であるサブクラステーブルであると仮定すると、エンティティに固有の列は実際には単なる関連付けられた値であり、代わりに関係をモデル化することを示唆します。個人とエンティティの間で1対1。このマッピングにより、必要な読み込み動作が正確に得られます。Personに対するクエリは「persons」に対してのみであり、Person.entityにアクセスすると、対応するエンティティを取得するための単一のSQLステートメントが発行されます。

  4. もう1つの考えは、ここで完全なマッピングを確認することはできませんが、「エンティティ」に「すべてのオブジェクトのベース」として機能する以外に意味のあるデータが実際に含まれていない場合、IMHOはアンチパターンです。リレーショナルDBが関係しています。Pythonで基本クラスを使用することは問題ありませんが、それに対応するデータベーステーブルは絶対にありません。それは、クエリと更新をはるかに困難にするだけです。

于 2012-10-31T02:47:44.623 に答える