1. 为什么需要会话工厂模式
在FastAPI项目中处理用户会话时,直接使用原始session对象会遇到几个典型问题。首先是会话初始化代码重复,每个路由都需要编写相同的session创建和关闭逻辑。其次是事务管理困难,当多个操作需要原子性执行时,缺乏统一的事务边界控制。最后是异常处理分散,每个路由都需要单独处理数据库异常。
会话工厂模式通过封装会话生命周期管理,提供了一种更优雅的解决方案。它本质上是一个生成和管理数据库会话的上下文管理器,主要解决以下问题:
- 资源泄漏风险:确保会话在使用后正确关闭,避免连接未释放
- 事务一致性:提供统一的事务提交/回滚控制点
- 代码复用:集中处理会话配置和异常处理逻辑
- 测试便利:可以轻松替换为测试用的会话实现
在FastAPI中实现会话工厂时,通常会结合SQLAlchemy的sessionmaker。下面是一个典型的问题场景:假设有一个用户注册接口,需要同时写入users表和profiles表。没有会话工厂时,代码可能长这样:
python复制@app.post("/register")
async def register(user_data: UserCreate):
session = SessionLocal()
try:
user = User(**user_data.dict())
session.add(user)
session.flush() # 需要先flush获取user.id
profile = Profile(user_id=user.id)
session.add(profile)
session.commit()
except Exception as e:
session.rollback()
raise HTTPException(status_code=400, detail=str(e))
finally:
session.close()
这种写法在每个路由中重复了会话管理代码,且事务边界不清晰。通过会话工厂重构后,代码可以简化为:
python复制@app.post("/register")
async def register(user_data: UserCreate, db: Session = Depends(get_db)):
user = User(**user_data.dict())
db.add(user)
db.flush()
profile = Profile(user_id=user.id)
db.add(profile)
# 不需要手动commit/rollback/close
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. FastAPI会话工厂的核心实现
2.1 基础会话工厂实现
一个完整的FastAPI会话工厂通常包含以下组件:
- 数据库连接配置:通过环境变量或配置类管理连接字符串
- 引擎创建:使用create_engine配置连接池等参数
- 会话工厂函数:生成可复用的sessionmaker实例
- 依赖项注入:创建
