Python ORM框架深度解析:SQLAlchemy实战
Python ORM框架深度解析SQLAlchemy实战引言大家好我是一名正在从Rust转向Python的后端开发者。在数据库操作方面ORMObject-Relational Mapping是一个非常重要的工具。它可以帮助我们将数据库表映射到Python对象从而避免直接编写SQL语句。作为从Rust过来的开发者我发现Python的SQLAlchemy是一个功能非常强大的ORM框架。今天我想和大家分享一下我在使用SQLAlchemy方面的一些经验。ORM概述什么是ORMORM是一种编程技术用于在关系型数据库和面向对象编程语言之间建立映射关系。它允许我们使用面向对象的方式来操作数据库而不需要直接编写SQL语句。ORM的优点代码可读性使用面向对象的方式操作数据库类型安全Python的类型系统可以提供一定的类型安全数据库无关性可以轻松切换数据库后端减少重复代码ORM会自动生成SQL语句SQLAlchemy架构应用层 ↓ SQLAlchemy CoreSQL表达式语言 ↓ SQLAlchemy ORM对象关系映射 ↓ 数据库引擎SQLite、MySQL、PostgreSQL等SQLAlchemy基础安装pip install sqlalchemy连接数据库from sqlalchemy import create_engine # SQLite engine create_engine(sqlite:///example.db) # MySQL engine create_engine(mysqlpymysql://user:passwordlocalhost/dbname) # PostgreSQL engine create_engine(postgresql://user:passwordlocalhost/dbname)定义模型from sqlalchemy import Column, Integer, String from sqlalchemy.ext.declarative import declarative_base Base declarative_base() class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) name Column(String(50)) email Column(String(100), uniqueTrue) age Column(Integer) def __repr__(self): return fUser(name{self.name}, email{self.email})创建表# 创建所有表 Base.metadata.create_all(engine)会话管理创建会话from sqlalchemy.orm import sessionmaker Session sessionmaker(bindengine) session Session()添加数据# 添加单条记录 user User(nameJohn, emailjohnexample.com, age30) session.add(user) session.commit() # 添加多条记录 users [ User(nameAlice, emailaliceexample.com, age25), User(nameBob, emailbobexample.com, age35) ] session.add_all(users) session.commit()查询数据# 查询所有 users session.query(User).all() # 条件查询 user session.query(User).filter_by(nameJohn).first() # 多条件查询 users session.query(User).filter(User.age 25, User.name.like(%o%)).all() # 排序 users session.query(User).order_by(User.age.desc()).all() # 限制结果数量 users session.query(User).limit(10).all()更新数据user session.query(User).filter_by(nameJohn).first() user.age 31 session.commit()删除数据user session.query(User).filter_by(nameJohn).first() session.delete(user) session.commit()高级查询连接查询from sqlalchemy import ForeignKey from sqlalchemy.orm import relationship class Address(Base): __tablename__ addresses id Column(Integer, primary_keyTrue) email Column(String(100)) user_id Column(Integer, ForeignKey(users.id)) user relationship(User, back_populatesaddresses) class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) name Column(String(50)) addresses relationship(Address, back_populatesuser) # 查询用户及其地址 users_with_addresses session.query(User).join(Address).all()聚合查询from sqlalchemy import func # 统计用户数量 count session.query(func.count(User.id)).scalar() # 计算平均年龄 avg_age session.query(func.avg(User.age)).scalar() # 分组统计 result session.query(User.name, func.count(Address.id)).join(Address).group_by(User.id).all()子查询subquery session.query(User.id).filter(User.age 30).subquery() users session.query(User).filter(User.id.in_(subquery)).all()关系映射一对一关系class Profile(Base): __tablename__ profiles id Column(Integer, primary_keyTrue) bio Column(String(500)) user_id Column(Integer, ForeignKey(users.id)) user relationship(User, back_populatesprofile, uselistFalse) class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) name Column(String(50)) profile relationship(Profile, back_populatesuser, uselistFalse)一对多关系class Post(Base): __tablename__ posts id Column(Integer, primary_keyTrue) title Column(String(100)) content Column(String(1000)) author_id Column(Integer, ForeignKey(users.id)) author relationship(User, back_populatesposts) class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) name Column(String(50)) posts relationship(Post, back_populatesauthor)多对多关系from sqlalchemy import Table # 关联表 user_role Table( user_role, Base.metadata, Column(user_id, Integer, ForeignKey(users.id)), Column(role_id, Integer, ForeignKey(roles.id)) ) class Role(Base): __tablename__ roles id Column(Integer, primary_keyTrue) name Column(String(50)) users relationship(User, secondaryuser_role, back_populatesroles) class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) name Column(String(50)) roles relationship(Role, secondaryuser_role, back_populatesusers)事务管理基本事务try: # 开始事务 user1 User(nameAlice, emailaliceexample.com) user2 User(nameBob, emailbobexample.com) session.add(user1) session.add(user2) # 提交事务 session.commit() except Exception as e: # 回滚事务 session.rollback() raise e嵌套事务# 保存点 session.begin_nested() try: user User(nameTest, emailtestexample.com) session.add(user) session.commit() except Exception as e: session.rollback()性能优化查询优化# 延迟加载默认 users session.query(User).all() for user in users: # 每次访问addresses都会触发额外查询 print(user.addresses) # 预先加载 users session.query(User).options(joinedload(User.addresses)).all() for user in users: # 不会触发额外查询 print(user.addresses) # 选择加载特定字段 users session.query(User.name, User.email).all()批量操作from sqlalchemy import insert, update, delete # 批量插入 stmt insert(User).values([ {name: Alice, email: aliceexample.com}, {name: Bob, email: bobexample.com} ]) session.execute(stmt) session.commit() # 批量更新 stmt update(User).where(User.age 30).values(age30) session.execute(stmt) session.commit() # 批量删除 stmt delete(User).where(User.name.like(%Test%)) session.execute(stmt) session.commit()实战项目完整的用户管理系统from sqlalchemy import create_engine, Column, Integer, String, DateTime, ForeignKey from sqlalchemy.ext.declarative import declarative_base from sqlalchemy.orm import sessionmaker, relationship from datetime import datetime # 创建引擎 engine create_engine(sqlite:///user_management.db) Base declarative_base() # 定义模型 class User(Base): __tablename__ users id Column(Integer, primary_keyTrue) username Column(String(50), uniqueTrue, nullableFalse) email Column(String(100), uniqueTrue, nullableFalse) password_hash Column(String(255), nullableFalse) created_at Column(DateTime, defaultdatetime.now) updated_at Column(DateTime, defaultdatetime.now, onupdatedatetime.now) profile relationship(UserProfile, back_populatesuser, uselistFalse) posts relationship(Post, back_populatesauthor) def __repr__(self): return fUser(username{self.username}, email{self.email}) class UserProfile(Base): __tablename__ user_profiles id Column(Integer, primary_keyTrue) user_id Column(Integer, ForeignKey(users.id)) first_name Column(String(50)) last_name Column(String(50)) bio Column(String(500)) location Column(String(100)) user relationship(User, back_populatesprofile) class Post(Base): __tablename__ posts id Column(Integer, primary_keyTrue) title Column(String(200), nullableFalse) content Column(String(5000), nullableFalse) author_id Column(Integer, ForeignKey(users.id)) created_at Column(DateTime, defaultdatetime.now) author relationship(User, back_populatesposts) # 创建表 Base.metadata.create_all(engine) # 创建会话 Session sessionmaker(bindengine) session Session() # 用户服务类 class UserService: def __init__(self, session): self.session session def create_user(self, username, email, password): # 检查用户是否已存在 existing_user self.session.query(User).filter( (User.username username) | (User.email email) ).first() if existing_user: raise ValueError(用户名或邮箱已存在) # 创建用户 user User( usernameusername, emailemail, password_hashpassword # 实际应用中应该使用bcrypt等加密 ) # 创建用户资料 profile UserProfile(useruser) self.session.add(user) self.session.add(profile) self.session.commit() return user def get_user_by_id(self, user_id): return self.session.query(User).filter_by(iduser_id).first() def get_user_by_email(self, email): return self.session.query(User).filter_by(emailemail).first() def update_user_profile(self, user_id, **kwargs): user self.get_user_by_id(user_id) if not user: raise ValueError(用户不存在) if user.profile: for key, value in kwargs.items(): setattr(user.profile, key, value) else: user.profile UserProfile(useruser, **kwargs) self.session.commit() return user def delete_user(self, user_id): user self.get_user_by_id(user_id) if not user: raise ValueError(用户不存在) self.session.delete(user) self.session.commit() # 使用示例 if __name__ __main__: service UserService(session) # 创建用户 user service.create_user(john_doe, johnexample.com, password123) print(f创建用户: {user}) # 更新用户资料 user service.update_user_profile(user.id, first_nameJohn, last_nameDoe, bioHello World) print(f更新资料: {user.profile.first_name} {user.profile.last_name}) # 查询用户 found_user service.get_user_by_email(johnexample.com) print(f查询用户: {found_user}) # 删除用户 service.delete_user(user.id) print(用户已删除)与Rust ORM的对比特性SQLAlchemyDiesel (Rust)类型安全通过类型提示编译时保证查询构建链式API宏和类型系统迁移工具第三方工具内置迁移支持异步支持SQLAlchemy 2.0原生支持性能较好更好总结SQLAlchemy是一个功能强大的ORM框架它提供了灵活的查询API支持复杂的查询操作强大的关系映射支持各种关系类型事务管理完整的事务支持性能优化支持预先加载、批量操作等通过合理使用SQLAlchemy我们可以提高代码的可读性和可维护性减少SQL语句的编写实现数据库无关性作为从Rust转向Python的开发者我发现SQLAlchemy虽然没有Rust的Diesel那样的编译时类型安全但它的灵活性和丰富功能使其成为Python生态中最受欢迎的ORM框架之一。延伸阅读SQLAlchemy官方文档SQLAlchemy 2.0新特性FastAPI SQLAlchemy教程