SQLAlchemy会话无法处理主键的query.update()

时间:2018-07-12 20:49:42

标签: python sqlalchemy

我的潜艇命令如下:

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关系也保持最新。

0 个答案:

没有答案