FastAPI 进阶(第二部分):SQLAlchemy ORM(含考题)

一、核心定义

SQLAlchemy 异步 ORM 是 SQLAlchemy 框架支持异步编程的对象关系映射模块,通过将 Python 业务模型类与关系型数据库表建立映射,允许开发者以 "操作 Python 对象" 的方式完成数据库交互,同时适配异步 I/O 模型,避免数据库操作阻塞事件循环,适配 FastAPI 等异步 Web 框架的开发需求。

**SQLAlchemy 的 4 个核心概念,**SQLAlchemy 是 Python 生态最强大的 ORM 框架,我们用它来关联 FastAPI 和 MySQL,具体如下:

Engine:数据库连接池(像 "餐厅的厨房")------ 管理数据库连接,避免每次操作都新建连接(费资源)。

Session:操作数据库的 "把手"(像 "服务员")------ 用它执行增删改查,用完要关闭。

Base:模型基类(像 "菜单模板")------ 所有数据库表对应的 Python 类都要继承它,它负责把类映射到表。

Model:具体的表类(像 "菜单上的菜")------ 比如User类对应users表,Role类对应roles表。

二、核心优势

异步非阻塞,提升并发性能:基于异步数据库驱动(如 aiomysql)实现,数据库操作(查询、写入等)不会阻塞主线程,同一时间可处理更多请求,尤其适合高并发场景。

ORM 特性复用,降低开发成本:继承传统 ORM 的核心价值,无需手动编写 SQL 语句,通过模型类、会话操作数据库;屏蔽不同数据库语法差异,提升代码可移植性。

与 FastAPI 深度协同:天然适配 FastAPI 的异步特性,支持通过依赖注入统一管理数据库会话,自动处理事务提交、回滚与连接释放,简化代码结构。

灵活的查询能力:支持条件查询、聚合查询、分页查询等复杂场景,保留 SQL 的灵活性,同时通过 Python 语法封装降低使用门槛。

资源自动管理 :通过 yield 语法与异步上下文管理器,实现数据库连接的自动创建、复用与关闭,配合连接池配置(如 pool_size),优化资源占用。

数据校验与结构化交互:可与 Pydantic 模型无缝结合,实现请求数据的校验与 ORM 模型的快速转换,确保数据安全性与结构化。

三、核心对比维度与优势总结​

|----------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------|
| 对比维度​ | SQLAlchemy 异步 ORM 优势​ | 其他异步 ORM 常见短板​ |
| 生态成熟度与兼容性​ | 1. 基于 SQLAlchemy 多年沉淀的核心生态,支持 MySQL、PostgreSQL、SQLite 等所有主流数据库;Alchemy 同步版的大部分 API,同步项目迁移异步成本极低;数据库特性(如事务隔离级别、存储过程、触发器)。​ | 1. 部分轻量框架(如 Tortoise)对小众数据库支持不足;>2. Django ORM 异步版依赖 Django 生态,脱离 Django 无法独立使用。​ |
| 查询灵活性与功能完备性​ | 1. 支持原生 SQL 混合查询、复杂 JOIN、子查询、窗口函数等高级 SQL 特性,兼顾 ORM 便捷性与 SQL 灵活性;. 提供强大的查询构造器,支持条件组合、聚合计算、分页排序等全场景需求(如你文档中 4.5 节的各类查询示例);、约束的精细化配置(如模型类中 mapped_column 的各类参数)。​ | 1. Tortoise ORM 等轻量框架查询语法简洁,但复杂查询能力有限,需手动拼接 SQL;2. Peewee-Async 功能较基础,不支持部分高级聚合查询。​ |
| 异步性能与资源管理​ | 1. 内置高效连接池(如文档中 pool_size、max_overflow 配置),支持连接复用与动态扩容,适配高并发场景;>2. 异步会话(AsyncSession)配合 yield 语法实现资源自动释放,避免连接泄露;生命周期管理(提交、回滚、嵌套事务)。​ | 1. 部分框架连接池配置简单,高并发下易出现连接耗尽;. 部分 ORM 异步事务支持不完整(如不支持嵌套事务)。​ |
| 与 FastAPI 协同性​ | 1. 天然适配 FastAPI 的异步特性与依赖注入系统(如文档中 get_database 依赖项,直接注入异步会话); Pydantic 深度兼容,支持模型类与 Pydantic 模型快速转换(如 4.5.5 节 BookBase 转 Book);API 接口文档生成,无需额外配置。​ | 1. 其他 ORM 需手动适配 FastAPI 依赖注入,代码冗余; 部分框架与 Pydantic 兼容性一般,需手动处理数据类型转换。​ |
| 扩展性与定制化能力​ | 1. 支持自定义类型映射、字段验证逻辑、查询拦截器等高级扩展; 系统监听数据库操作生命周期(如模型创建、更新前的钩子函数);支持数据库迁移工具(Alembic),适配项目迭代中的 schema 变更。​ | 1. 轻量 ORM 扩展点少,定制化能力弱;工具,需手动维护 SQL 脚本。​ |
| 学习成本与社区支持​ | 1. 文档完善、社区活跃,问题解决方案丰富(如你参考的 CSDN 实战文章、官方文档); API 风格一致,熟悉同步 SQLAlchemy 的开发者可快速上手;工具集成(如日志、监控、测试工具)。​ | 1. 部分小众框架文档简陋,社区支持有限;异步版需先掌握 Django 生态,学习成本高。​ |

四、SQLAlchemy 异步 ORM 整合(核心实战)

4.1 ORM 核心简介

定义:Object Relational Mapping(对象关系映射),实现 Python 对象与关系型数据库的映射。

核心价值

操作 Python 对象即可实现数据库交互,无需手动编写 SQL;

屏蔽数据库语法差异,提升代码可移植性;

简化数据库操作,降低开发成本和出错概率。

4.2 异步数据库配置(引擎、会话)
4.2.1 核心依赖导入

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| from datetime import datetime from sqlalchemy import DateTime, func, String, Float, select from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSession from fastapi import Depends, HTTPException from pydantic import BaseModel from sqlalchemy.orm import DeclarativeBase, Mapped, mapped_column |

4.2.2 步骤 1:定义数据库连接 URL

|-----------------------------------------------------------------------------------------------------------------------------------------------|
| # MySQL异步连接URL格式:数据库类型+异步驱动://用户名:密码@地址:端口/数据库名?编码 ASYNC_DATABASE_URL = "mysql+aiomysql://root:1234@localhost:3306/fastapi_test?charset=utf8" |

4.2.3 步骤 2:创建异步数据库引擎

|---------------------------------------------------------------------------------------------------------------------------------------------|
| async_engine = create_async_engine( ASYNC_DATABASE_URL, echo=True, # 开启SQL日志(调试用) pool_size=10, # 连接池常驻连接数 max_overflow=20 # 高并发时额外允许的连接数 ) |

4.2.4 步骤 3:创建异步会话工厂

|-----------------------------------------------------------------------------------------------------------------------------------------|
| AsyncSessionLocal = async_sessionmaker( bind=async_engine, # 绑定异步引擎 class_=AsyncSession, # 指定异步会话类型 expire_on_commit=False # 提交后会话不过期 ) |

4.2.5 步骤 4:定义数据库会话依赖项

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| async def get_database(): async with AsyncSessionLocal() as session: try: yield session # 注入会话给路由 await session.commit() # 无异常提交事务 except Exception: await session.rollback() # 异常回滚 raise finally: await session.close() # 关闭会话释放连接 |

4.3 定义 ORM 模型类
4.3.1 步骤 1:模型基类(公共字段复用)

|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| class Base(DeclarativeBase): # 公共字段:创建时间、更新时间 create_time: Mapped[datetime] = mapped_column( DateTime, insert_default=func.now(), default=func.now(), comment="创建时间" ) update_time: Mapped[datetime] = mapped_column( DateTime, insert_default=func.now(), default=func.now(), onupdate=func.now(), comment="更新时间" ) |

4.3.2 步骤 2:业务模型类(书籍表)

|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| class Book(Base): tablename = "book" # 数据库表名 id: Mapped[int] = mapped_column(primary_key=True, comment="书籍ID") # 主键 bookname: Mapped[str] = mapped_column(String(255), comment="书名") author: Mapped[str] = mapped_column(String(255), comment="作者") price: Mapped[float] = mapped_column(Float, comment="价格") publisher: Mapped[str] = mapped_column(String(255), comment="出版社") |

4.4 应用启动自动建表

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 建表函数 async def create_tables(): async with async_engine.begin() as conn: await conn.run_sync(Base.metadata.create_all) # 创建所有模型对应的表 # FastAPI启动事件:项目启动时执行建表 @app.on_event("startup") async def startup_event(): await create_tables() |

4.5 ORM 数据库完整操作(增删改查)
4.5.1 基础查询(所有 / 单条 / 按主键)

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 1. 查询所有书籍 @app.get("/book/books") async def get_book_list(db: AsyncSession = Depends(get_database)): result = await db.execute(select(Book)) return result.scalars().all() # 2. 查询单条书籍(第一条) @app.get("/book/bookOne") async def get_book_single(db: AsyncSession = Depends(get_database)): result = await db.execute(select(Book)) return result.scalars().first() # 3. 按主键查询(高效) @app.get("/book/bookGet") async def get_book_by_id(db: AsyncSession = Depends(get_database)): return await db.get(Book, 1) # 参数:模型类 + 主键值 |

4.5.2 条件查询(比较 / 模糊 / 逻辑 / 包含)

|-------|-----------------------------------------------------------------------------------------|
| 查询类型 | 核心语法示例 |
| 多条件比较 | select(Book).where(Book.id==book_id, Book.bookname==book_name, Book.price<=book_price) |
| 模糊查询 | select(Book).where(Book.author.like(f"{author}%"))(% 匹配任意字符) |
| 逻辑与 | `select(Book).where(Book.author.like(f"{author}%") & (Book.price |
| 逻辑或 | `select(Book).where(Book.author.like(f"{author}%") |

4.5.3 聚合查询(统计 / 均值 / 最值 / 求和)

|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # 1. 价格平均值 @app.get("/book/count") async def get_book_price_avg(db: AsyncSession = Depends(get_database)): result = await db.execute(select(func.avg(Book.price))) return {"avg_price": result.scalar()} # 2. 价格最大值 @app.get("/book/max") async def get_book_price_max(db: AsyncSession = Depends(get_database)): result = await db.execute(select(func.max(Book.price))) return {"max_price": result.scalar()} # 3. 价格总和 @app.get("/book/sum") async def get_book_price_sum(db: AsyncSession = Depends(get_database)): result = await db.execute(select(func.sum(Book.price))) return {"sum_price": result.scalar()} |

4.5.4 分页查询

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| @app.get("/book/get_books") async def get_book_paginate( page: int = 1, page_size: int = 3, db: AsyncSession = Depends(get_database) ): skip = (page - 1) * page_size # 分页核心公式:跳过条数 = (页码-1)*每页条数 stmt = select(Book).offset(skip).limit(page_size) result = await db.execute(stmt) return result.scalars().all() |

4.5.5 新增数据

|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # Pydantic模型(数据校验) class BookBase(BaseModel): id: int; bookname: str; author: str; price: float; publisher: str # 新增接口 @app.post("/book/add_book") async def add_book(book: BookBase, db: AsyncSession = Depends(get_database)): book_obj = Book(**book.dict()) # Pydantic转ORM对象 db.add(book_obj) # 添加到事务 return book # 依赖项自动提交事务 |

4.5.6 更新数据

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| # Pydantic模型(更新数据校验) class BookUpdate(BaseModel): bookname: str; author: str; price: float; publisher: str # 更新接口 @app.put("/book/update_book/{book_id}") async def update_book(id: int, book: BookUpdate, db: AsyncSession = Depends(get_database)): book1 = await db.get(Book, id) if not book1: raise HTTPException(status_code=404, detail="Book not found") # 重新赋值更新 book1.bookname = book.bookname; book1.price = book.price; book1.author = book.author; book1.publisher = book.publisher return book1 |

4.5.7 删除数据

|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| @app.delete("/book/delete_book/{book_id}") async def delete_book(book_id: int, db: AsyncSession = Depends(get_database)): db_book = await db.get(Book, book_id) if not db_book: raise HTTPException(status_code=404, detail="book not found") await db.delete(db_book) # 删除对象 return {"message": "book is deleted"} |

五、项目测试与验证

前置条件:启动 MySQL 服务,创建fastapi_test数据库;

启动项目:执行 FastAPI 运行命令;

访问文档:http://127.0.0.1:8000/docs(自动生成的交互式接口文档);

测试顺序:先新增书籍 → 再执行查询 / 更新 / 删除 → 查看控制台 SQL 日志和返回结果,验证功能正确性。

六、核心知识点考题

题目 1:关于 SQLAlchemy 异步 ORM 的生态成熟度与兼容性,以下说法正确的有()

A. 支持 MySQL、PostgreSQL、SQLite 等主流数据库,对小众数据库支持无短板​

B. 兼容 SQLAlchemy 同步版大部分 API,同步项目迁移异步成本低​

C. 支持事务隔离级别、存储过程、触发器等复杂数据库特性​

D. 依赖特定 Web 框架生态,无法独立在异步 Python 项目中使用​

答案:BC​

解析:A 错误,原文未提及 SQLAlchemy 对小众数据库无短板,反而指出部分轻量框架(如 Tortoise)小众数据库支持不足,SQLAlchemy 虽支持主流数据库,但未强调 "无短板";B 对应 "同步项目迁移异步成本极低" 的描述;C 符合 "支持复杂数据库特性(如事务隔离级别、存储过程、触发器)";D 错误,SQLAlchemy 异步 ORM 是独立模块,无额外生态绑定,而 Django ORM 异步版才依赖 Django 生态。​

题目 2:SQLAlchemy 异步 ORM 在查询灵活性与功能完备性上的优势包括()​

A. 支持原生 SQL 混合查询、复杂 JOIN、子查询、窗口函数等高级特性​

B. 提供强大查询构造器,支持条件组合、聚合计算、分页排序等全场景需求​

C. 模型类中可通过 mapped_column 精细化配置索引、约束​

D. 复杂查询需手动拼接 SQL,灵活性低于轻量 ORM 框架​

答案:ABC​

解析:D 错误,原文明确 "Tortoise ORM 等轻量框架复杂查询能力有限,需手动拼接 SQL",而 SQLAlchemy 无需手动拼接,灵活性更强;A、B 对应 "支持原生 SQL 混合查询、复杂 JOIN 等高级 SQL 特性""提供强大的查询构造器,支持条件组合、聚合计算、分页排序等全场景需求";C 符合 "支持数据库索引、约束的精细化配置(如模型类中 mapped_column 的各类参数)"。​

题目 3:关于 SQLAlchemy 异步 ORM 的异步性能与资源管理,正确的描述有()

A. 内置高效连接池,支持 pool_size、max_overflow 等配置,适配高并发​

B. 异步会话(AsyncSession)配合 yield 语法实现资源自动释放,避免连接泄露​

C. 支持异步事务的完整生命周期管理(提交、回滚、嵌套事务)​

D. 连接池配置固定,高并发下易出现连接耗尽问题​

答案:ABC​

解析:D 错误,"连接池配置固定,高并发下易出现连接耗尽" 是其他框架的短板,SQLAlchemy 支持精细化配置;A 对应 "内置高效连接池(如文档中 pool_size、max_overflow 配置),支持连接复用与动态扩容";B 符合 "异步会话(AsyncSession)配合 yield 语法实现资源自动释放";C 对应 "支持异步事务的完整生命周期管理(提交、回滚、嵌套事务)"。​

题目 4:SQLAlchemy 异步 ORM 与 FastAPI 的协同性优势体现在()​

A. 天然适配 FastAPI 的异步特性与依赖注入系统,可直接注入异步会话​

B. 与 Pydantic 深度兼容,支持模型类与 Pydantic 模型快速转换​

C. 需手动配置才能集成 FastAPI 接口文档生成功能​

D. 其他 ORM 需手动适配依赖注入,代码冗余度高于 SQLAlchemy​

答案:ABD​

解析:C 错误,原文明确 SQLAlchemy 异步 ORM"自动集成 FastAPI 接口文档生成,无需额外配置";A 对应 "天然适配 FastAPI 的异步特性与依赖注入系统(如文档中 get_database 依赖项,直接注入异步会话)";B 符合 "与 Pydantic 深度兼容,支持模型类与 Pydantic 模型快速转换(如 4.5.5 节 BookBase 转 Book)";D 对应 "其他 ORM 需手动适配 FastAPI 依赖注入,代码冗余"。​

题目 5:以下关于 SQLAlchemy 异步 ORM 扩展性与社区支持的说法,正确的有()​

A. 支持自定义类型映射、字段验证逻辑、查询拦截器等高级扩展​

B. 可通过 event 系统监听数据库操作生命周期(如模型创建、更新前的钩子函数)​

C. 支持数据库迁移工具(Alembic),适配项目迭代中的 schema 变更​

D. 文档简陋、社区支持有限,学习成本高于小众 ORM 框架​

答案:ABC​

解析:D 错误,"文档简陋、社区支持有限" 是小众框架的短板,SQLAlchemy 文档完善、社区活跃,且熟悉同步版的开发者可快速上手,学习成本更低;A、B 对应 "支持自定义类型映射、字段验证逻辑、查询拦截器等高级扩展;可通过 event 系统监听数据库操作生命周期";C 符合 "支持数据库迁移工具(Alembic),适配项目迭代中的 schema 变更"。​

相关推荐
c***03232 小时前
Mysql之主从复制
android·数据库·mysql
向哆哆2 小时前
道路表面多类型缺陷的图像识别数据集分享(适用于目标检测任务)
人工智能·目标检测·计算机视觉
p***19942 小时前
MySQL Workbench菜单汉化为中文
android·数据库·mysql
格林威2 小时前
Baumer相机药瓶铝盖压合完整性检测:防止密封失效的 7 个关键技术,附 OpenCV+Halcon 实战代码!
人工智能·opencv·计算机视觉·视觉检测·工业相机·智能相机·堡盟相机
数据知道2 小时前
PostgreSQL:如何配置数据库的传输层加密(SSL加密连接)
数据库·postgresql·ssl
發糞塗牆2 小时前
【Azure 架构师学习笔记 】- Azure AI(6)-Azure认知服务-Document Intelligence简单使用
人工智能·ai·azure
计算机视觉-Archer2 小时前
【参考文献】【国自然基金&毕业论文】Word参考文献排版---格式推荐
人工智能
山岚的运维笔记2 小时前
SQL Server笔记 -- 第55章:外键
数据库·笔记·sql·microsoft·sqlserver
wsfk12342 小时前
MySQL 数据库连接池爆满问题排查与解决
android·数据库·mysql