ORM框架原理
ORM(Object-Relational Mapping)将关系数据库映射为对象模型,消除 SQL 与面向对象编程的阻抗失配。
核心概念
对象关系映射
Python
数据库表 ←→ Python 类
表字段 ←→ 类属性
表记录 ←→ 类实例
外键关系 ←→ 对象引用
映射示例
Python
# 数据库表
CREATE TABLE users (
id INTEGER PRIMARY KEY,
name VARCHAR(50),
email VARCHAR(100)
);
# ORM 映射
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
name = Column(String(50))
email = Column(String(100))
核心实现机制
1. 元数据映射
Python
# SQLAlchemy 示例
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_key=True)
name = Column(String(50))
# 元数据存储表结构信息
print(User.__table__) # Table对象
2. 工作单元模式(Unit of Work)
Python
# Django ORM 示例
user = User.objects.get(id=1) # 查询
user.name = 'New Name' # 修改(未写入数据库)
user.save() # 提交到数据库
# SQLAlchemy Session
session = Session()
user = session.query(User).get(1)
user.name = 'New Name'
session.commit() # 批量提交所有变更
3. 延迟加载(Lazy Loading)
Python
# 关联对象延迟加载
user = session.query(User).first()
# 此时未加载 posts
posts = user.posts # 访问时才执行查询
4. 查询构建器
Python
# SQLAlchemy 查询构建
query = session.query(User).filter(User.age > 18).order_by(User.name)
# 等价 SQL
# SELECT * FROM users WHERE age > 18 ORDER BY name
# Django ORM
User.objects.filter(age__gt=18).order_by('name')
关系映射
一对多
Python
class User(Base):
__tablename__ = 'users'
id = Column(Integer, primary_key=True)
posts = relationship('Post', back_populates='user')
class Post(Base):
__tablename__ = 'posts'
id = Column(Integer, primary_key=True)
user_id = Column(Integer, ForeignKey('users.id'))
user = relationship('User', back_populates='posts')
多对多
Python
# 需要中间表
student_course = Table(
'student_course', Base.metadata,
Column('student_id', Integer, ForeignKey('students.id')),
Column('course_id', Integer, ForeignKey('courses.id'))
)
class Student(Base):
__tablename__ = 'students'
id = Column(Integer, primary_key=True)
courses = relationship('Course', secondary=student_course, back_populates='students')
class Course(Base):
__tablename__ = 'courses'
id = Column(Integer, primary_key=True)
students = relationship('Student', secondary=student_course, back_populates='courses')
N+1 查询问题
问题示例
Python
# N+1 问题
users = session.query(User).all() # 1 次查询
for user in users:
print(user.posts) # N 次查询(每个 user 都查询一次 posts)
解决方案:预加载
text
# joinedload - JOIN 查询
users = session.query(User).options(joinedload(User.posts)).all()
# selectinload - IN 查询
users = session.query(User).options(selectinload(User.posts)).all()
# Django prefetch_related
User.objects.prefetch_related('posts')
主流 ORM 框架对比
| 特性 | Django ORM | SQLAlchemy | Peewee |
|---|---|---|---|
| 学习曲线 | 低 | 中高 | 低 |
| 灵活性 | 中 | 高 | 中 |
| 性能控制 | 中 | 高 | 高 |
| 复杂查询 | 弱 | 强 | 中 |
| 数据库支持 | 多种 | 多种 | 多种 |
| 独立使用 | 不推荐 | 推荐 | 推荐 |
Django ORM 适合 Django 项目,SQLAlchemy 适合独立项目或复杂场景。
要点总结
- ORM 核心是将表映射为类、记录映射为实例
- 工作单元模式批量管理对象状态变更
- 延迟加载提升性能,但需警惕 N+1 问题
- 复杂查询可回退到原生 SQL
- SQLAlchemy 灵活性最高,Django ORM 最易上手
📝 发现内容有误?点击此处直接编辑