title: FastAPI中的依赖注入与数据库事务管理

date: 2025/04/09 00:10:29

updated: 2025/04/09 00:10:29

author: cmdragon

excerpt:

FastAPI中使用依赖注入和SQLAlchemy进行数据库会话封装的方法,提供了三种事务管理模式的实现:自动事务模式、手动控制模式和装饰器模式。通过代码示例展示了如何创建用户注册功能,并处理事务和错误。强调了使用参数化查询防止SQL注入攻击的重要性,并提供了常见报错的解决方案,包括检查数据库连接参数、管理会话生命周期和调整连接池设置。

categories:

  • 后端开发
  • FastAPI

tags:

  • 依赖注入
  • 数据库会话管理
  • 事务管理
  • FastAPI
  • SQLAlchemy
  • 异步编程
  • SQL注入防护


扫描二维码关注或者微信搜一搜:编程智域 前端至全栈交流与成长

探索数千个预构建的 AI 应用,开启你的下一个伟大创意

  1. 依赖注入基础与数据库会话封装

    (代码示例运行环境:Python 3.8+,需安装fastapi, uvicorn, sqlalchemy, asyncpg)
from fastapi import Depends, FastAPI
from sqlalchemy.ext.asyncio import AsyncSession, create_async_engine
from sqlalchemy.orm import sessionmaker # 初始化数据库连接(使用异步引擎)
DATABASE_URL = "postgresql+asyncpg://user:password@localhost/dbname"
engine = create_async_engine(DATABASE_URL, echo=True)
async_session_maker = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False) # 封装数据库会话依赖
async def get_db() -> AsyncSession:
"""
生成器函数创建数据库会话上下文
使用yield代替return实现资源自动释放
会话自动关闭机制保证连接池回收
"""
async with async_session_maker() as session:
try:
yield session
finally:
await session.close() app = FastAPI() @app.post("/users/")
async def create_user(
name: str,
session: AsyncSession = Depends(get_db)
):
"""
路由函数通过Depends自动获取数据库会话
事务管理需要在业务逻辑中显式控制
注意异步await关键字的正确使用
"""
from sqlalchemy import text
try:
# 执行原生SQL示例(实际建议使用ORM)
await session.execute(
text("INSERT INTO users (name) VALUES (:name)"),
{"name": name}
)
await session.commit()
return {"status": "created"}
except Exception as e:
await session.rollback()
raise HTTPException(500, str(e))
  1. 事务管理的三种实现模式

(1)自动事务模式(适合简单操作):

from fastapi import Depends
from databases import Database async def transaction_wrapper(db: Database = Depends(get_db)):
async with db.transaction():
yield

(2)手动控制模式(复杂业务场景):

@app.post("/orders/")
async def create_order(
user_id: int,
db: AsyncSession = Depends(get_db)
):
try:
await db.begin()
# 执行多个数据库操作
await db.commit()
except SQLAlchemyError:
await db.rollback()
raise

(3)装饰器模式(代码复用最佳实践):

from contextlib import asynccontextmanager

@asynccontextmanager
async def managed_transaction(db: AsyncSession):
try:
yield
await db.commit()
except Exception:
await db.rollback()
raise # 在路由中使用
async def create_order(db: AsyncSession = Depends(get_db)):
async with managed_transaction(db):
# 业务逻辑代码
  1. 完整案例:用户注册连带创建档案

    (包含事务管理和错误处理的最佳实践)
from sqlalchemy import insert
from pydantic import BaseModel class UserCreate(BaseModel):
username: str
email: str
profile: dict @app.post("/register/")
async def register_user(
user_data: UserCreate,
db: AsyncSession = Depends(get_db)
):
async with db.begin():
try:
# 插入用户主表
user_result = await db.execute(
insert(users_table).values(
username=user_data.username,
email=user_data.email
).returning(users_table.c.id)
)
user_id = user_result.scalar() # 插入档案子表
await db.execute(
insert(profiles_table).values(
user_id=user_id,
**user_data.profile
)
) return {"user_id": user_id} except IntegrityError as e:
await db.rollback()
if "unique constraint" in str(e):
raise HTTPException(400, "Username already exists")
raise HTTPException(500, "Database error")

课后Quiz:

Q1:使用原生SQL查询时,如何防止SQL注入攻击?

A) 直接拼接字符串

B) 使用参数化查询

C) 过滤特殊字符

D) 使用ORM自动处理

正确答案:B

解析:参数化查询通过将用户输入与SQL语句分离的方式,从根本上阻止注入攻击。示例中的text()

函数配合参数字典即为正确做法。即使用ORM,也需要避免直接拼接查询字符串。

常见报错解决方案:

错误现象:

sqlalchemy.exc.InterfaceError: (sqlalchemy.dialects.postgresql.asyncpg.InterfaceError) <class 'asyncpg.exceptions.ConnectionDoesNotExistError'>

原因分析:

  1. 数据库连接参数配置错误
  2. 连接池耗尽未正确释放
  3. 异步上下文管理不当

解决步骤:

  1. 检查DATABASE_URL格式:postgresql+asyncpg://
  2. 确保数据库服务正常运行
  3. 在依赖项中正确使用async with管理会话生命周期
  4. 调整连接池设置:
engine = create_async_engine(
DATABASE_URL,
pool_size=20,
max_overflow=10,
pool_timeout=30
)

余下文章内容请点击跳转至 个人博客页面 或者 扫码关注或者微信搜一搜:编程智域 前端至全栈交流与成长,阅读完整的文章:FastAPI中的依赖注入与数据库事务管理 | cmdragon's Blog

往期文章归档:

FastAPI中的依赖注入与数据库事务管理的更多相关文章

  1. Spring学习(三)——Spring中的依赖注入的方式

    [前面的话] Spring对我太重要了,做个关于web相关的项目都要使用Spring,每次去看Spring相关的知识,总是感觉一知半解,没有很好的系统去学习一下,现在抽点时间学习一下Spring.不知 ...

  2. ABP中的依赖注入思想

    在充分理解整个ABP系统架构之前首先必须充分了解ABP中最重要的依赖注入思想,在后面会具体举出一些实例来帮助你充分了解ABP中的依赖注入思想,在了解这个之前我们首先来看看什么是依赖注入?来看看维基百科 ...

  3. 深入理解net core中的依赖注入、Singleton、Scoped、Transient(四)

    相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transient(一) 深入理解net core中的依赖注入.Singleton.Scoped.Transient ...

  4. ASP.NET Core 中的依赖注入

    目录 什么是依赖注入 ASP .NET Core 中使用依赖注入 注册 使用 释放 替换为其它的 Ioc 容器 参考 什么是依赖注入 软件设计原则中有一个依赖倒置原则(DIP),为了更好的解耦,讲究要 ...

  5. Android 和 Dagger 2 中的依赖注入

    原文:Dependency Injection in Android with Dagger 2 作者:Joe Howard 译者:kmyhy 在现代开发团队中到处充斥着"你一定要用依赖注入 ...

  6. 深入理解net core中的依赖注入、Singleton、Scoped、Transient(四)【转】

    原文链接:https://www.cnblogs.com/gdsblog/p/8465401.html 相关文章: 深入理解net core中的依赖注入.Singleton.Scoped.Transi ...

  7. ADO.NET .net core2.0添加json文件并转化成类注入控制器使用 简单了解 iTextSharp实现HTML to PDF ASP.NET MVC 中 Autofac依赖注入DI 控制反转IOC 了解一下 C# AutoMapper 了解一下

    ADO.NET   一.ADO.NET概要 ADO.NET是.NET框架中的重要组件,主要用于完成C#应用程序访问数据库 二.ADO.NET的组成 ①System.Data  → DataTable, ...

  8. ASP.NET Core 中的 依赖注入介绍

    ASP.NET Core 依赖注入 HomeController public class HomeController : Controller { private IStudentReposito ...

  9. ASP.NET Core 中文文档 第四章 MVC(3.8)视图中的依赖注入

    原文:Dependency injection into views 作者:Steve Smith 翻译:姚阿勇(Dr.Yao) 校对:孟帅洋(书缘) ASP.NET Core 支持在视图中使用 依赖 ...

  10. 在WPF中使用依赖注入的方式创建视图

    在WPF中使用依赖注入的方式创建视图 0x00 问题的产生 互联网时代桌面开发真是越来越少了,很多应用都转到了浏览器端和移动智能终端,相应的软件开发上的新技术应用到桌面开发的文章也很少.我之前主要做W ...

随机推荐

  1. JavaWeb的一些理解

    WEB概述 WEB是什么 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上的资源分类 Internet上供外界访问的Web资源分为: 静态 ...

  2. javascript对象学习笔记

    目前所见的,在普通的JavaScript应用中和绝大多数人一样使用的是全局的方式.大概是因为JavaScript所定义的变量或函数默认就是全局的.为了是代码不至于太凌乱,变量不至于稀里糊涂的就被人重定 ...

  3. 从存钱罐到子数组:一个关于累加和的精妙问题|LeetCode 560 和为K的子数组

    LeetCode 560 和为K的子数组 点此看全部题解 LeetCode必刷100题:一份来自面试官的算法地图(题解持续更新中) 生活中的算法 你有没有这样的经历:每天往存钱罐里存一些零钱,某一天突 ...

  4. 云数据库与Web网站:构建高效、可扩展的网络应用

    本文分享自天翼云开发者社区<云数据库与Web网站:构建高效.可扩展的网络应用>,作者:3****m 一.云数据库与Web网站的关系 云数据库与Web网站之间存在着密切的关系.Web网站需要 ...

  5. FLink17--全窗口聚合方法1--ApplyWindowApp

    一.依赖 二.代码 package net.xdclass.class11; import java.util.List; import java.util.stream.Collectors; im ...

  6. C# 获取计算机唯一标识

    C# 获取计算机唯一标识 原文链接 private static string _sFingerPrint { get; set; } /// <summary> /// 计算机唯一标识 ...

  7. 库卡机器人KR120示教器日常保养技巧

              库卡机器人KR120是一款高效.精准的工业机器人,广泛应用于各个领域.然而,要确保其长期稳定运行,日常的保养和维护至关重要.下面,我们将为您介绍库卡机器人KR120示教器的日常保养 ...

  8. .NET MCP项目对比分析:MCPSharp、mcpdotnet与ModelContextProtocol.NET

    MCP(Model Context Protocol)协议是一种由Anthropic推出的开放协议,旨在实现大型语言模型(LLM)与外部数据源和工具之间的无缝集成.简要对比分析三个.NET的MCP项目 ...

  9. Elasticsearch搜索引擎学习笔记(五)

    搜索功能 数据准备 1.自定义词库 慕课网 慕课 课网 慕 课 网 2.新建立索引shop 3.建立mappings POST /shop/_mapping (7.x之前的版本:/shop/_mapp ...

  10. MyBatis与其使用方法讲解

    ORM 在讲解Mybatis之前,我们需了解一个概念ORM(Object-Relational Mapping)对象关系映射,其是数据库与Java对象进行映射的一个技术.通过使用ORM,我们可以不用编 ...