FastAPI依赖中Session操作及幕后with块的理解疑问
session.add(db_hero)
这行是把内存中的db_hero对象注册到当前数据库会话(Session)中,相当于给SQLModel/SQLAlchemy“报备”:这个对象需要存入数据库。这一步不会立刻执行SQL写入,只是在会话的内存队列里标记了这个新增操作。
session.commit()
这是真正触发数据库写入的操作。它会把会话中所有待执行的变更(这里就是新增Hero)打包成SQL语句发送给数据库,完成数据持久化。同时会结束当前数据库事务——commit成功则变更永久生效,失败则事务自动回滚。
session.refresh(db_hero)
很多数据库表会有自动生成的字段(比如自增id、创建时间created_at),这些值是数据库在插入时生成的,commit之后内存里的db_hero对象还没有这些数据。refresh()就是从数据库拉回刚插入记录的最新数据,更新内存中的对象,让你返回的结果包含这些自动生成的字段值。
那段描述的核心是:虽然create_hero函数里没写显式的with块,但你的业务代码依然运行在Session的上下文环境中——这是FastAPI依赖注入机制帮你做的隐式处理。
通常get_session依赖的实现会用yield返回Session,比如:
def get_session(): with Session(engine) as session: yield session
FastAPI处理请求时,会自动把create_hero的执行逻辑包裹在这个with块里:请求进来时,进入with块创建Session并注入给函数;请求处理完毕(无论成功或失败),自动退出with块,触发Session的close(),有异常时还会自动回滚事务。
说白了就是你不用手动写with块,但背后的运行逻辑和显式写with完全一致——会话的开启、上下文管理、关闭全由依赖注入自动搞定。
内容的提问来源于stack exchange,提问作者Alwaysblue

