使用SQLAlchemy

Python ORM 教程:使用 SQLAlchemy 进行数据库操作

在当今的应用开发中,数据库操作是不可或缺的一部分。本文将介绍如何使用 Python 中最流行的 ORM 框架 SQLAlchemy 来简化数据库操作,提高开发效率。

1. ORM 简介

ORM(Object-Relational Mapping,对象关系映射)是一种编程技术,用于在面向对象编程语言中实现不同类型系统的数据转换。在数据库操作中,ORM 将数据库表结构映射到对象上,使开发者可以用面向对象的方式操作数据库。

1.1 传统方式 vs ORM 方式

在不使用 ORM 的情况下,我们从数据库查询得到的数据通常是元组形式:

传统方式(使用元组):

[
 ('1', 'Michael'),
 ('2', 'Bob'),
 ('3', 'Adam')
]

这种方式虽然直接,但不够直观,特别是在处理复杂关系时。而 ORM 则允许我们用更自然的对象方式来处理数据:

ORM 方式(使用对象):

class User:
    def __init__(self, id, name):
        self.id = id
        self.name = name

[
 User('1', 'Michael'),
 User('2', 'Bob'),
 User('3', 'Adam')
]

通过 ORM,我们可以像操作普通对象一样操作数据库记录,大大提升了代码的可读性和可维护性。

2. SQLAlchemy 安装与配置

SQLAlchemy 是 Python 中最成熟的 ORM 框架之一,提供了完整的企业级持久化模式。

2.1 安装 SQLAlchemy

首先,我们需要安装 SQLAlchemy 核心包:

pip install sqlalchemy

对于 MySQL 数据库,还需要安装对应的驱动:

pip install mysql-connector-python
# 或者
pip install pymysql

2.2 基本配置

安装完成后,我们需要进行基本配置:

from sqlalchemy import create_engine, Column, String, Integer, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.orm import declarative_base

# 创建基类
Base = declarative_base()

# 数据库连接配置
DATABASE_URL = "mysql+mysqlconnector://username:password@localhost:3306/database_name"
engine = create_engine(DATABASE_URL)

# 创建会话工厂
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

3. 定义模型

在 SQLAlchemy 中,模型是与数据库表对应的 Python 类。

3.1 基本模型定义

下面是一个简单的用户模型定义:

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50))
    email = Column(String(100), unique=True, index=True)

3.2 关系模型定义

SQLAlchemy 的强大之处在于它能够轻松处理表之间的关系。下面是一个一对多关系的例子:

class User(Base):
    __tablename__ = 'users'
    
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String(50))
    email = Column(String(100), unique=True, index=True)
    # 一对多关系
    posts = relationship("Post", back_populates="author")

class Post(Base):
    __tablename__ = 'posts'
    
    id = Column(Integer, primary_key=True, index=True)
    title = Column(String(100))
    content = Column(String(1000))
    author_id = Column(Integer, ForeignKey('users.id'))
    # 多对一关系
    author = relationship("User", back_populates="posts")

4. 数据库操作

有了模型定义后,我们可以开始进行数据库操作了。

4.1 创建表

首先,我们需要创建数据库表:

Base.metadata.create_all(bind=engine)

4.2 CRUD 操作

下面我们将介绍基本的增删改查操作。

创建记录

def create_user(name: str, email: str):
    db = SessionLocal()
    try:
        db_user = User(name=name, email=email)
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user
    finally:
        db.close()

查询记录

# 查询所有用户
def get_users():
    db = SessionLocal()
    try:
        return db.query(User).all()
    finally:
        db.close()

# 查询单个用户
def get_user(user_id: int):
    db = SessionLocal()
    try:
        return db.query(User).filter(User.id == user_id).first()
    finally:
        db.close()

# 带条件的查询
def get_user_by_email(email: str):
    db = SessionLocal()
    try:
        return db.query(User).filter(User.email == email).first()
    finally:
        db.close()

更新记录

def update_user(user_id: int, name: str, email: str):
    db = SessionLocal()
    try:
        db_user = db.query(User).filter(User.id == user_id).first()
        if db_user:
            db_user.name = name
            db_user.email = email
            db.commit()
            db.refresh(db_user)
        return db_user
    finally:
        db.close()

删除记录

def delete_user(user_id: int):
    db = SessionLocal()
    try:
        db_user = db.query(User).filter(User.id == user_id).first()
        if db_user:
            db.delete(db_user)
            db.commit()
        return db_user
    finally:
        db.close()

4.3 关系操作

除了基本操作外,SQLAlchemy 还提供了方便的关系操作:

# 创建带关系的记录
def create_user_with_posts(name: str, email: str, posts: list):
    db = SessionLocal()
    try:
        db_user = User(name=name, email=email)
        for post in posts:
            db_post = Post(**post)
            db_user.posts.append(db_post)
        db.add(db_user)
        db.commit()
        db.refresh(db_user)
        return db_user
    finally:
        db.close()

# 查询带关系的记录
def get_user_with_posts(user_id: int):
    db = SessionLocal()
    try:
        return db.query(User).filter(User.id == user_id).options(
            joinedload(User.posts)
        ).first()
    finally:
        db.close()

5. 高级特性

SQLAlchemy 提供了许多高级特性,让我们来看两个重要的例子。

5.1 事务管理

事务管理是数据库操作的重要部分,SQLAlchemy 提供了简单的方式来处理事务:

def transfer_funds(from_id: int, to_id: int, amount: float):
    db = SessionLocal()
    try:
        from_account = db.query(Account).filter(Account.id == from_id).first()
        to_account = db.query(Account).filter(Account.id == to_id).first()
        
        if not from_account or not to_account:
            raise ValueError("Account not found")
            
        if from_account.balance < amount:
            raise ValueError("Insufficient funds")
            
        from_account.balance -= amount
        to_account.balance += amount
        
        db.commit()
    except Exception as e:
        db.rollback()
        raise e
    finally:
        db.close()

5.2 异步支持(SQLAlchemy 2.0+)

SQLAlchemy 2.0+ 提供了异步支持,适合高并发场景:

from sqlalchemy.ext.asyncio import create_async_engine, AsyncSession
from sqlalchemy.orm import sessionmaker

async def get_async_db():
    DATABASE_URL = "mysql+asyncmy://username:password@localhost:3306/database_name"
    engine = create_async_engine(DATABASE_URL)
    async_session = sessionmaker(engine, class_=AsyncSession, expire_on_commit=False)
    
    async with async_session() as session:
        yield session

async def async_get_user(user_id: int):
    async with get_async_db() as db:
        result = await db.execute(select(User).where(User.id == user_id))
        return result.scalars().first()

6. 最佳实践

以下是使用 SQLAlchemy 的一些最佳实践:

  1. 使用上下文管理器:确保会话总是被正确关闭
  2. 避免长事务:保持事务尽可能短小
  3. 批量操作:对于大量数据,使用批量操作提高性能
  4. 合理使用关系加载:根据需要选择立即加载或延迟加载
  5. 使用类型提示:提高代码可读性和IDE支持

7. 总结

SQLAlchemy 是一个功能强大且灵活的 Python ORM 框架,它提供了从简单的 CRUD 操作到复杂的关系处理等各种数据库操作功能。通过使用 ORM,开发者可以更专注于业务逻辑而不是数据库细节,同时还能保持对 SQL 的完全控制能力。

随着 SQLAlchemy 2.0 的发布,它提供了更好的类型支持和异步操作能力,使其成为现代 Python 应用程序的理想选择。无论你是刚开始接触 ORM,还是已经有一定经验,SQLAlchemy 都能为你的项目带来显著的开发效率提升。