db.refresh(obj)或者重新crud或者设置expire_no_commit=False解决
SQLAlchemy Session机制研究SQLAlchemy是Python中经常使用的一种对象关系映射模型(Obje - 掘金
Session中实现了一种叫做Identity Map的映射表,并且会把当前Session上下文中从数据库查询结果集的每一行记录都映射为一个Python对象保存到Identity Map中,Map的key就是行的主键
待提交图片
project对象在session过期
expire=True
class Project(Base):
__tablename__ = 'project'
id = Column(Integer, primary_key=True)
name = Column(String)
class Machine(Base):
__tablename__ = 'machine'
id = Column(Integer, primary_key=True)
project_id = Column(Integer, ForeignKey('project.id'))
serial_number = Column(String)
删除了一个
Project
对象,这个对象的 ID 作为外键关联到多个Machine
对象。SQLAlchemy 会将所有与这个Project
对象相关联的Machine
对象标记为过期,以反映数据库中Project
对象的删除状态。这是因为这些Machine
对象现在可能处于一个无效的状态或需要重新加载其最新的状态如果
project
实例在Session
中缓存了对Machine
的引用,删除Machine
可能会使project
的状态标记为过期,以便在下次访问时重新加载它
四种状态
在 SQLAlchemy 中,一个对象在 Session
中可以有四种主要状态,这些状态定义了对象在事务中的生命周期以及它与数据库的关系。这些状态是:
1. Transient(临时)
定义:对象处于
transient
状态时,表示它是一个新创建的对象,但还没有被添加到Session
中。特点:
- 这个对象没有关联的数据库记录。
- 对象的主键属性通常是未定义的(或者为
None
)。 - 对象没有被 SQLAlchemy 的
Session
管理。 - 需要将其添加到
Session
中,才能进入persistent
状态。
new_object = MyModel() # 临时状态
2. Persistent(持久)
定义:对象处于
persistent
状态时,表示它已经被添加到Session
中并且在数据库中有一个对应的记录。特点:
- 对象的状态与数据库中的记录保持同步。
- 对象的主键属性已经设置并且在数据库中存在对应记录。
- 对象在
Session
中被跟踪,可以被更新、删除或重新加载。
db.add(new_object) # 现在对象进入持久状态
3. Detached(分离)
定义:对象处于
detached
状态时,表示它曾经是persistent
状态的对象,但现在已经从Session
中分离出来。特点:
- 对象在数据库中可能仍然存在,但不再由当前的
Session
管理。 - 对象的状态不再与数据库同步,任何对对象的修改都不会反映到数据库中,直到重新添加到
Session
。 - 对象可能因为调用
session.remove()
、session.commit()
或者因为Session
被关闭而变为detached
状态。
db.remove(existing_object) # 对象进入分离状态
- 对象在数据库中可能仍然存在,但不再由当前的
4. Deleted(已删除)
定义:对象处于
deleted
状态时,表示它已被标记为删除,将会从数据库中删除。特点:
- 对象在
Session
中被标记为待删除,但实际上尚未从数据库中删除,只有在调用session.commit()
时才会实际删除。 - 在
commit()
之前,对象仍然可以恢复到persistent
状态(通过session.add()
)或者被Session
重新管理。
db.delete(existing_object) # 对象标记为已删除
- 对象在
状态转换
- 从
transient
到persistent
:通过db.add(object)
将临时对象添加到Session
中。 - 从
persistent
到detached
:通过db.remove(object)
或Session
关闭将持久对象从Session
中移除。 - 从
persistent
到deleted
:通过db.delete(object)
将持久对象标记为删除。 - 从
deleted
到persistent
:在调用commit()
之前,可以通过db.add(object)
恢复删除标记。
使用实例
假设你有一个模型 MyModel
,并进行以下操作:
from sqlalchemy.orm import Session
from my_model import MyModel
# 创建一个新的会话
session = Session()
# 临时状态
obj = MyModel(name='example')
# 添加到会话,将其转变为持久状态
session.add(obj)
# 提交事务,将持久对象保存到数据库
session.commit()
# 删除对象,将其标记为已删除
session.delete(obj)
# 提交事务,实际从数据库中删除对象
session.commit()
# 对象现在是分离状态
了解这些状态有助于有效地管理对象的生命周期,并确保它们在不同操作和事务中的正确行为。
评论区