数据库项目如何进行分层设计?
在一个后端项目中,数据库相关代码需要进行合理分层,避免模型定义、数据库连接、业务操作全部混杂在一起。
一个推荐的结构如下:
1 | src/ |
一、models 层:负责数据库模型定义
models 目录主要负责定义数据库中的表结构。
目录结构
1 | /src/models |
1. init.py
__init__.py 的作用是初始化模型模块。
例如:
1 | from src.models.user import UserModel |
为什么需要提前导入模型?
因为 SQLAlchemy 在执行:
1 | Base.metadata.create_all(bind=engine) |
时,需要提前知道有哪些模型存在。
如果没有导入对应的模型文件,Base 可能不知道有哪些数据表需要创建,最终导致数据库初始化时无法生成对应表。
所以:
init.py 的作用就是提前加载并注册所有模型,让 SQLAlchemy 能够识别完整的表结构。
2. base.py
base.py 负责定义所有模型的基类。
例如:
1 | from sqlalchemy.orm import DeclarativeBase |
所有数据库模型都会继承这个 Base。
例如:
1 | class UserModel(Base): |
这样做的好处:
- 统一管理所有模型
- 方便 SQLAlchemy 创建数据表
- 降低模型之间的耦合
3. user.py
user.py 负责具体的数据表定义。
例如:
1 | class UserModel(Base): |
每一个模型文件对应数据库中的一张表。
二、db 层:负责数据库操作
目录:
1 | /src/db |
crud.py 主要负责数据库的增删改查操作。
例如:
- 创建用户
- 查询用户
- 修改用户信息
- 删除用户
需要注意:
crud 层只负责数据库 CRUD,不应该包含业务逻辑。
例如:
错误:
1 | create_user() |
正确:
1 | create_user() |
业务逻辑应该交给 service 层处理。
三、database.py:负责数据库连接管理
database.py 是数据库连接的核心文件。
它主要暴露两个功能:
- 初始化数据库
- 提供数据库 Session
1. 创建数据库连接
1 | from sqlalchemy import create_engine |
这里导入:
1 | from src.models.base import Base |
非常重要。
它会触发 models 包加载,使 SQLAlchemy 提前知道有哪些模型。
2. 创建 Session 工厂
1 | SessionLocal = sessionmaker( |
SessionLocal 用于创建数据库会话。
每一次数据库操作,都需要通过 Session 与数据库交互。
3. 初始化数据库
1 | def init_db(): |
这个函数通常会在 FastAPI 启动时调用。
作用:
- 创建不存在的数据表
- 初始化数据库结构
4. 提供数据库 Session
1 | def get_db(): |
这个函数主要给 FastAPI 的依赖注入使用。
流程:
1 | 请求进入 |
这样可以保证数据库连接及时释放。
总结:各层职责
| 文件 | 职责 |
|---|---|
| models/ | 定义数据库表结构 |
| models/base.py | 提供 ORM 基类 |
| models/init.py | 注册所有模型 |
| models/user.py | 定义具体表 |
| db/crud.py | 负责数据库增删改查 |
| database.py | 管理数据库连接和 Session |
整体设计思想:
模型负责描述数据,crud 负责操作数据,database.py 负责管理连接。
通过这种分层方式,可以让数据库代码更加清晰,方便后期扩展和维护。