Python 数据访问与 SQLAlchemy

数据访问层隔离 SQL/ORM;SQLAlchemy 为核心生态之一,需理解会话、事务与 N+1。

#type / concept #status / growing #tech / dev #resource / python #tech / lang / python

[!info] 关联笔记

Python 数据访问与 SQLAlchemy

这个概念为什么出现

业务若直接拼 SQL 字符串,会散落注入风险与事务边界混乱。数据访问层(Repository/DAO)+ ORM/查询构建器提供结构,但 ORM 不是免费午餐(N+1、隐式 IO)。

[!abstract] 一句话理解 把持久化细节关在数据层;SQLAlchemy 提供 Core/ORM,会话与事务界定工作单元,查询行为必须可观察。

最小可运行示例

场景:内存演示“仓储接口”而非真实 DB

# repo_pattern_demo.py
# 业务意图:用内存仓储表达数据层边界(无 DB 依赖)。
# 教学点:接口隔离;业务不拼存储细节。

from dataclasses import dataclass


@dataclass
class User:
    id: str
    email: str


class UserRepository:
    def __init__(self) -> None:
        self._rows: dict[str, User] = {}

    def add(self, user: User) -> None:
        self._rows[user.id] = user

    def get(self, user_id: str) -> User | None:
        return self._rows.get(user_id)


def register(repo: UserRepository, user_id: str, email: str) -> User:
    user = User(user_id, email)
    repo.add(user)
    return user


def main() -> None:
    repo = UserRepository()
    register(repo, "u1", "a@example.com")
    print(repo.get("u1"))


if __name__ == "__main__":
    main()

建议运行:

python repo_pattern_demo.py

期望输出:

User(id='u1', email='a@example.com')

结合场景再看三个关注点

  1. 业务依赖仓储接口,便于测。
  2. 真实 SQLAlchemy:Engine/Session/映射。
  3. 谨防延迟加载触发隐式查询。

核心概念与准确模型

  • Engine 连接池
  • Session/Unit of Work
  • Core SQL 表达式 vs ORM
  • 迁移工具(Alembic)

边界情况与反直觉行为

  1. N+1
  2. 会话生命周期 与 web 请求绑定
  3. 跨进程身份映射

常见误区

[!warning] 常见误区:ORM 对象当跨层 DTO 到处传 错误理解:省转换。
正确模型:边界用明确 schema,避免会话剥离问题。

工程实践

  • 事务边界清晰
  • 慢查询日志
  • 迁移版本化

本节总结

数据访问是正确性与性能交汇点。先边界,后 ORM 技巧。

自测题

  1. 仓储模式收益?
  2. N+1 是什么?
参考答案
  1. 业务与存储解耦、可测试。
  2. 循环中每次额外查询,放大延迟。

延伸阅读与资料来源

资料类型支撑内容
SQLAlchemy文档ORM/Core
创建于 2026/7/15 更新于 2026/7/15