Inheritance Patterns

Advanced Alchemy provides robust support for SQLAlchemy’s inheritance patterns, ensuring that mixins and common attributes are correctly applied across the hierarchy.

Common Table Attributes

When using inheritance, it is recommended to use the CommonTableAttributes mixin. This ensures that table names are correctly generated and that shared attributes (like primary keys or audit columns) are inherited properly.

from sqlalchemy.orm import DeclarativeBase
from advanced_alchemy.base import CommonTableAttributes, orm_registry

class Base(CommonTableAttributes, DeclarativeBase):
    registry = orm_registry

Single Table Inheritance (STI)

In STI, multiple classes are mapped to a single table. A “discriminator” column is used to determine which class a particular row represents.

from typing import Optional
from sqlalchemy.orm import Mapped
from advanced_alchemy.base import UUIDAuditBase

class Employee(UUIDAuditBase):
    __tablename__ = "employee"
    name: Mapped[str]
    type: Mapped[str]

    __mapper_args__ = {
        "polymorphic_on": "type",
        "polymorphic_identity": "employee",
    }

class Manager(Employee):
    __mapper_args__ = {
        "polymorphic_identity": "manager",
    }
    manager_data: Mapped[Optional[str]]

class Engineer(Employee):
    __mapper_args__ = {
        "polymorphic_identity": "engineer",
    }
    engineer_info: Mapped[Optional[str]]
from sqlalchemy.orm import Mapped
from advanced_alchemy.base import UUIDAuditBase

class Employee(UUIDAuditBase):
    __tablename__ = "employee"
    name: Mapped[str]
    type: Mapped[str]

    __mapper_args__ = {
        "polymorphic_on": "type",
        "polymorphic_identity": "employee",
    }

class Manager(Employee):
    __mapper_args__ = {
        "polymorphic_identity": "manager",
    }
    manager_data: Mapped[str | None]

class Engineer(Employee):
    __mapper_args__ = {
        "polymorphic_identity": "engineer",
    }
    engineer_info: Mapped[str | None]

Joined Table Inheritance (JTI)

In JTI, each class in the hierarchy is mapped to its own table. Sub-tables contain only the columns specific to that class and a foreign key to the parent table.

from uuid import UUID

from sqlalchemy import ForeignKey
from sqlalchemy.orm import Mapped, mapped_column
from advanced_alchemy.base import UUIDAuditBase

class Person(UUIDAuditBase):
    __tablename__ = "person"
    name: Mapped[str]
    type: Mapped[str]

    __mapper_args__ = {
        "polymorphic_on": "type",
        "polymorphic_identity": "person",
    }

class Staff(Person):
    __tablename__ = "staff"
    id: Mapped[UUID] = mapped_column(ForeignKey("person.id"), primary_key=True)
    staff_no: Mapped[str]

    __mapper_args__ = {
        "polymorphic_identity": "staff",
    }

Concrete Table Inheritance (CTI)

In CTI, each class is mapped to a completely independent table containing all columns for that class.

from sqlalchemy.orm import Mapped
from advanced_alchemy.base import UUIDAuditBase

class Vehicle(UUIDAuditBase):
    __abstract__ = True
    name: Mapped[str]

class Car(Vehicle):
    __tablename__ = "car"
    engine_type: Mapped[str]

class Bicycle(Vehicle):
    __tablename__ = "bicycle"
    has_basket: Mapped[bool]

Repository Usage with Inheritance

Advanced Alchemy’s repositories work seamlessly with inheritance. You can create a repository for the base class to query across all types, or for a specific subclass.

from sqlalchemy.ext.asyncio import AsyncSession

from advanced_alchemy.repository import SQLAlchemyAsyncRepository

class EmployeeRepository(SQLAlchemyAsyncRepository[Employee]):
    model_type = Employee

async def list_employees(db_session: AsyncSession) -> list[Employee]:
    repository = EmployeeRepository(session=db_session)
    return await repository.list()

class ManagerRepository(SQLAlchemyAsyncRepository[Manager]):
    model_type = Manager

async def list_managers(db_session: AsyncSession) -> list[Manager]:
    repository = ManagerRepository(session=db_session)
    return await repository.list()