sqlalchemy级联一记
下面详细介绍 SQLAlchemy 里单对单级联、单对多级联和多对多级联的实现,以及对应的 CRUD 操作,同时给出完整的代码示例。
单对单级联
实现思路
单对单关系意味着一个父对象只关联一个子对象,子对象也只关联一个父对象。可以通过设置 relationship
中的 uselist=False
来表示单对单关系,并且使用 cascade
参数实现级联操作。
代码示例
from sqlalchemy import create_engine, Column, Integer, String, ForeignKey
from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.ext.declarative import declarative_base
# 创建基类
Base = declarative_base()
# 定义单对单关系的模型
class Parent(Base):
__tablename__ = 'parent'
id = Column(Integer, primary_key=True)
name = Column(String)
# 单对单关系,设置级联操作
child = relationship("Child", back_populates="parent", uselist=False, cascade="all, delete-orphan")
class Child(Base):
__tablename__ = 'child'
id = Column(Integer, primary_key=True)
name = Column(String)
parent_id = Column(Integer, ForeignKey('parent.id'))
parent = relationship("Parent", back_populates="child")
# 创建数据库引擎
engine = create_engine('sqlite:///test.db')
# 创建表
Base.metadata.create_all(engine)
# 创建会话
Session = sessionmaker(bind=engine)
session = Session()
# 创建操作
def create_one_to_one():
parent = Parent(name='Parent')
child = Child(name='Child')
parent.child = child
session.add(parent)
session.commit()
return parent
# 读取操作
def read_one_to_one():
parent = session.query(Parent).first()
if parent:
print(f"Parent: {parent.name}, Child: {parent.child.name if parent.child else 'No child'}")
return parent
# 更新操作
def update_one_to_one():
parent = session.query(Parent).first()
if parent:
parent.name = 'Updated Parent'
if parent.child:
parent.child.name = 'Updated Child'
session.commit()
return parent
# 删除操作
def delete_one_to_one():
parent = session.query(Parent).first()
if parent:
session.delete(parent)
session.commit()
单对多级联
实现思路
单对多关系表示一个父对象可以关联多个子对象,子对象只关联一个父对象。使用 relationship
建立关联,cascade
参数实现级联操作。
代码示例
# 定义单对多关系的模型
class Team(Base):
__tablename__ = 'team'
id = Column(Integer, primary_key=True)
name = Column(String)
# 单对多关系,设置级联操作
players = relationship("Player", back_populates="team", cascade="all, delete-orphan")
class Player(Base):
__tablename__ = 'player'
id = Column(Integer, primary_key=True)
name = Column(String)
team_id = Column(Integer, ForeignKey('team.id'))
team = relationship("Team", back_populates="players")
# 创建操作
def create_one_to_many():
team = Team(name='Team A')
player1 = Player(name='Player 1')
player2 = Player(name='Player 2')
team.players.extend([player1, player2])
session.add(team)
session.commit()
return team
# 读取操作
def read_one_to_many():
team = session.query(Team).first()
if team:
print(f"Team: {team.name}, Players: {[player.name for player in team.players]}")
return team
# 更新操作
def update_one_to_many():
team = session.query(Team).first()
if team:
team.name = 'Updated Team'
for player in team.players:
player.name = f"Updated {player.name}"
session.commit()
return team
# 删除操作
def delete_one_to_many():
team = session.query(Team).first()
if team:
session.delete(team)
session.commit()
多对多级联
实现思路
多对多关系需要一个中间表来关联两个实体。通过 relationship
的 secondary
参数指定中间表,并使用 cascade
实现级联操作。
代码示例
# 定义中间表
association_table = Table('association', Base.metadata,
Column('student_id', Integer, ForeignKey('student.id')),
Column('course_id', Integer, ForeignKey('course.id'))
)
# 定义多对多关系的模型
class Student(Base):
__tablename__ = 'student'
id = Column(Integer, primary_key=True)
name = Column(String)
# 多对多关系,设置级联操作
courses = relationship("Course", secondary=association_table, back_populates="students", cascade="all, delete")
class Course(Base):
__tablename__ = 'course'
id = Column(Integer, primary_key=True)
name = Column(String)
students = relationship("Student", secondary=association_table, back_populates="courses")
# 创建操作
def create_many_to_many():
student = Student(name='Student')
course1 = Course(name='Course 1')
course2 = Course(name='Course 2')
student.courses.extend([course1, course2])
session.add(student)
session.commit()
return student
# 读取操作
def read_many_to_many():
student = session.query(Student).first()
if student:
print(f"Student: {student.name}, Courses: {[course.name for course in student.courses]}")
return student
# 更新操作
def update_many_to_many():
student = session.query(Student).first()
if student:
student.name = 'Updated Student'
for course in student.courses:
course.name = f"Updated {course.name}"
session.commit()
return student
# 删除操作
def delete_many_to_many():
student = session.query(Student).first()
if student:
session.delete(student)
session.commit()
测试代码
if __name__ == "__main__":
# 单对单关系操作
print("One-to-One Relationship:")
create_one_to_one()
read_one_to_one()
update_one_to_one()
read_one_to_one()
delete_one_to_one()
# 单对多关系操作
print("\nOne-to-Many Relationship:")
create_one_to_many()
read_one_to_many()
update_one_to_many()
read_one_to_many()
delete_one_to_many()
# 多对多关系操作
print("\nMany-to-Many Relationship:")
create_many_to_many()
read_many_to_many()
update_many_to_many()
read_many_to_many()
delete_many_to_many()
session.close()
代码解释
- 单对单关系:
Parent
和Child
模型通过relationship
建立一对一关联,uselist=False
明确为单对单,cascade="all, delete-orphan"
确保父对象删除时子对象也被删除。 - 单对多关系:
Team
和Player
模型建立一对多关联,Team
可关联多个Player
,同样使用cascade="all, delete-orphan"
实现级联删除。 - 多对多关系:
Student
和Course
通过中间表association_table
建立多对多关联,cascade="all, delete"
保证删除学生时相关课程关联也被删除。
注意事项
- 上述代码使用 SQLite 数据库,你可以根据需求更换数据库引擎。
- 每次操作完成后记得提交会话(
session.commit()
)和关闭会话(session.close()
)。