11-SQLAlchemy 2.0异步ORM实战指南

SQLAlchemy 2.0异步ORM实战指南

前言

SQLAlchemy 2.0引入了原生异步支持,为高性能数据库操作提供了强大工具。本文将详细介绍如何使用SQLAlchemy 2.0构建异步数据访问层。

适合读者: 后端开发者、数据库工程师


一、模型定义

python 复制代码
# models/user.py
from sqlalchemy import String, Integer, DateTime, Boolean
from sqlalchemy.orm import Mapped, mapped_column
from datetime import datetime
from database import Base

class User(Base):
    __tablename__ = "users"
    
    id: Mapped[int] = mapped_column(Integer, primary_key=True)
    username: Mapped[str] = mapped_column(String(50), unique=True, index=True)
    email: Mapped[str] = mapped_column(String(100), unique=True, index=True)
    password_hash: Mapped[str] = mapped_column(String(255))
    full_name: Mapped[str | None] = mapped_column(String(100))
    is_active: Mapped[bool] = mapped_column(Boolean, default=True)
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

class Conversation(Base):
    __tablename__ = "conversations"
    
    id: Mapped[str] = mapped_column(String(36), primary_key=True)
    user_id: Mapped[int] = mapped_column(Integer, ForeignKey("users.id"))
    title: Mapped[str] = mapped_column(String(200))
    created_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow)
    updated_at: Mapped[datetime] = mapped_column(DateTime, default=datetime.utcnow, onupdate=datetime.utcnow)

二、CRUD操作

python 复制代码
# crud/user.py
from sqlalchemy import select, update, delete
from sqlalchemy.ext.asyncio import AsyncSession

async def create_user(db: AsyncSession, username: str, email: str, password_hash: str):
    user = User(username=username, email=email, password_hash=password_hash)
    db.add(user)
    await db.flush()
    await db.refresh(user)
    return user

async def get_user_by_id(db: AsyncSession, user_id: int):
    result = await db.execute(select(User).where(User.id == user_id))
    return result.scalar_one_or_none()

async def get_users(db: AsyncSession, skip: int = 0, limit: int = 100):
    result = await db.execute(select(User).offset(skip).limit(limit))
    return result.scalars().all()

async def update_user(db: AsyncSession, user_id: int, **kwargs):
    await db.execute(
        update(User).where(User.id == user_id).values(**kwargs)
    )
    return await get_user_by_id(db, user_id)

async def delete_user(db: AsyncSession, user_id: int):
    await db.execute(delete(User).where(User.id == user_id))

三、关系查询

python 复制代码
# 一对多关系
from sqlalchemy.orm import relationship

class User(Base):
    __tablename__ = "users"
    id: Mapped[int] = mapped_column(primary_key=True)
    conversations: Mapped[list["Conversation"]] = relationship(back_populates="user")

class Conversation(Base):
    __tablename__ = "conversations"
    id: Mapped[str] = mapped_column(primary_key=True)
    user_id: Mapped[int] = mapped_column(ForeignKey("users.id"))
    user: Mapped["User"] = relationship(back_populates="conversations")

# 查询用户及其对话
async def get_user_with_conversations(db: AsyncSession, user_id: int):
    result = await db.execute(
        select(User)
        .options(selectinload(User.conversations))
        .where(User.id == user_id)
    )
    return result.scalar_one_or_none()

四、事务管理

python 复制代码
async def transfer_conversation(
    db: AsyncSession,
    conversation_id: str,
    from_user_id: int,
    to_user_id: int
):
    async with db.begin():
        # 检查对话是否存在
        conv = await get_conversation(db, conversation_id)
        if not conv or conv.user_id != from_user_id:
            raise ValueError("对话不存在或无权限")
        
        # 更新对话所有者
        conv.user_id = to_user_id
        await db.flush()

五、性能优化

python 复制代码
# 批量插入
async def batch_create_messages(db: AsyncSession, messages: list[dict]):
    db.add_all([Message(**msg) for msg in messages])
    await db.flush()

# 预加载关系
from sqlalchemy.orm import selectinload, joinedload

async def get_conversations_with_messages(db: AsyncSession, user_id: int):
    result = await db.execute(
        select(Conversation)
        .options(selectinload(Conversation.messages))
        .where(Conversation.user_id == user_id)
    )
    return result.scalars().all()

下一篇预告: 《Redis缓存策略:提升API响应速度10倍》

相关推荐
ZPC82103 分钟前
OLOv11 + 深度相机的方案实现高精度3D定位
人工智能·数码相机·算法·机器人
星辰yzy4 分钟前
个人用户怎么选AI套餐更划算
人工智能
weixin_457760006 分钟前
基于pytorch实现LPR模型车牌识别
人工智能·pytorch·python·深度学习·lpr
市象8 分钟前
AWE观察:一面“魔镜”照亮全屋智能,AI卫浴迎来新场景
人工智能·健康医疗·制造
Dfreedom.8 分钟前
机器学习经典算法全景解析与演进脉络(监督学习篇)
人工智能·学习·算法·机器学习·监督学习
华农DrLai8 分钟前
什么是Prompt注入攻击?为什么恶意输入能操控AI行为?
人工智能·深度学习·大模型·nlp·prompt
吃杠碰小鸡17 分钟前
Python+Ai学习流程
人工智能·python·学习
奔袭的算法工程师17 分钟前
用AI写天线阵列排布算法
人工智能·算法·信号处理
夏星印25 分钟前
学习吴恩达课程机器学习笔记
人工智能·笔记·学习·机器学习·ai