我的潜艇命令如下:
class Ord(Base):
__tablename__ = 'ords'
id = Column(Integer, primary_key=True)
subs = relationship('Sub', back_populates='ord', cascade="all, delete, delete-orphan")
class Sub(Base):
__tablename__ = 'subs'
oid = Column(Integer, ForeignKey('ords.id', onupdate="cascade", ondelete="cascade"), primary_key=True)
id = Column(Integer, primary_key=True)
假设我想将Sub(PK的一部分)的ID增加10:
self.session.query(Sub).filter(and_(Sub.oid==2, Sub.id > 1)).update({Sub.id: Sub.id + 10})
这有效并产生所需的结果。但是,当我再次运行同一命令时,它将引发以下内容:
ObjectDeletedError:实例“ Sub at 0x197daf597b8”已被删除,或者不存在该行。
我试图刷新会话中的对象,甚至session.expire_all()
都没有作用。
如何重新使我的SQLAlchemy会话完整?
P.S .:从会话工厂中生成一个新会话,并用self.session代替上面的“解决”问题,并允许再次运行查询。听起来我的原始会话有某种缺陷。
P.P.S .:这是一个重现该问题的低级日志:
session_factory = sessionmaker(bind=c.engine)
ses1=session_factory()
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1})
ses1.commit()
# OK
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1})
ses1.commit()
# OK
sub0 = ses1.query(Ses).filter_by(oid=2, id=26).one()
sub0
# Sub(2, 26)
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1})
ses1.commit()
# OK
sub0
# ObjectDeletedError
ses1.expire_all()
sub0
# ObjectDeletedError
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1})
# ObjectDeletedError
del sub0
sub0
# NameError: name 'sub0' is not defined
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1})
# ObjectDeletedError
因此,看来对sub0的引用变得无效,并且现在无法正确解决。另一方面,我没有在代码中的任何地方明确保留引用-这是SQLAlchemy内部错误。即使session.refresh()无法治愈它,session.expore_all()也绝对可以解决。
解决方案,归功于@IljaEverilä:
ses1.query(Sub).filter(and_(Sub.oid==2, Sub.id>1)).update({Sub.id: Sub.id + 1},
synchronize_session='fetch')
这仍然使我的sub0参考无效,但至少现在会话保持为一体,并且subs
关系也保持最新。