Choosing how to represent the inheritance is mostly a database design issue. For performance single table inheritance is usually best. From a good database design point of view, joined table inheritance is better. Joined table inheritance enables you to have foreign keys to subclasses enforced by the database, it's a lot simpler to have non-null constraints for subclass fields. Concrete table inheritance is kind of worst of both worlds.
Single table inheritance setup with declarative looks like this:
class Building(Base):
__tablename__ = 'building'
id = Column(Integer, primary_key=True)
building_type = Column(String(32), nullable=False)
x = Column(Float, nullable=False)
y = Column(Float, nullable=False)
__mapper_args__ = {'polymorphic_on': building_type}
class Commercial(Building):
__mapper_args__ = {'polymorphic_identity': 'commercial'}
business = Column(String(50))
class Residential(Building):
__mapper_args__ = {'polymorphic_identity': 'residential'}
num_residents = Column(Integer)
To make it joined table inheritance, you'll need to add
__tablename__ = 'commercial'
id = Column(None, ForeignKey('building.id'), primary_key=True)
to the subclasses.
Querying is mostly the same with both approaches:
# buildings that are within x>5 and y>3
session.query(Building).filter((Building.x > 5) & (Building.y > 3))
# Residential buildings that have only 1 resident
session.query(Residential).filter(Residential.num_residents == 1)
To control which fields are loaded you can use the query.with_polymorphic()
method.
The most important thing to think about using inheritance for the datamapping, is whether you actually need inheritance or can do with aggregation. Inheritance will be a pain if you will ever need to change the type of an building, or your buildings can have both commercial and residential aspects. In those cases it's usually better to have the commercial and residential aspects as related objects.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…