在 Sqlalchemy 中,在类关系属性中附加对象两次时出现奇怪的行为

发布于 2024-12-10 15:45:45 字数 1345 浏览 0 评论 0原文

我在学习 SQLAlchemy 时遇到一些奇怪的问题。我正在使用它的0.7.2版本。这些是我的测试类:

    class User(Base):
        __tablename__ = 'users'

        id = Column('user_id',Integer,primary_key = True)
        name = Column('user_name',String(20))

        addresses = relationship("Address",backref="user")

        def __repr__(self):
              return "<User(%s)>" % self.name

    class Address(Base):
          __tablename__ = 'addresses'

          id = Column('adress_id',Integer,primary_key = True)
          address = Column('address',String(30))
          user_id = Column('user_id',ForeignKey('users.user_id'))

          def __repr__(self):
               return "<Address(%s)>" % self.address
  1. 我不小心运行了主文件两次,这使得以下代码运行了两次

    会话 = sessionmaker()
    会话=会话(绑定=引擎)
    q=session.query(用户)
    a=q.get(3)
    a.addresses.append(地址(address='myaddress'))
    会话.flush()
    打印a.addresses[0].id,a.addresses[0].address
    

    我最初认为 a.addresses 会有两个带有“myaddress”的地址对象。但实际上只有一个对象的address_id被更新了。我的意思是说,当我首先运行文件时,它打印了

    1,'我的地址'
    
    然后在第二次运行时打印
    
    2、'我的地址'
    

我通过打印 a.addresses 确认仅存在 Address 对象,并且它只显示其中的对象。

难道它不应该在追加时在 a.addresses 中添加第二个 Address 对象,而不是更新现有地址对象的 id 吗?

请注意,没有执行 session.commit() 命令。我只是运行该文件两次并注意到了这种行为。

编辑:添加了创建新会话并负责解决问题的代码,如下面答案中 van 所建议的那样

I am facing some odd problems while learning SQLAlchemy. I am using 0.7.2 version of it. These are my test classes:

    class User(Base):
        __tablename__ = 'users'

        id = Column('user_id',Integer,primary_key = True)
        name = Column('user_name',String(20))

        addresses = relationship("Address",backref="user")

        def __repr__(self):
              return "<User(%s)>" % self.name

    class Address(Base):
          __tablename__ = 'addresses'

          id = Column('adress_id',Integer,primary_key = True)
          address = Column('address',String(30))
          user_id = Column('user_id',ForeignKey('users.user_id'))

          def __repr__(self):
               return "<Address(%s)>" % self.address
  1. I accidentally ran my main file twice which made following code run twice

    Session = sessionmaker()
    session = Session(bind=engine)
    q=session.query(User)
    a=q.get(3)
    a.addresses.append(Address(address='myaddress'))
    session.flush()
    print a.addresses[0].id,a.addresses[0].address
    

    I initially thought that a.addresses would have got two address object with 'myaddress'. But actually there is only one object whose address_id got updated. I mean to say when I ran file first it printed

    1,'myaddress'
    
    and then in second run it printed
    
    2,'myaddress'
    

I confirmed existence of only Address object by printing a.addresses and it shows only object in it.

Should it not add a second Address object in a.addresses on append instead of updating id of existing address object?

Note there is no session.commit() command executed. I simply ran the file twice and noticed this behaviour.

Edit : Added code which creates new session and is responsible for the problem as suggested by van below in the answer

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

欲拥i 2024-12-17 15:45:45

这在您的代码中看不到,但我假设执行两次的代码也在两个不同的会话中执行。这可以解释您观察到的所有副作用

  • 只有一个地址:因为第二个会话不知道第一个(未提交)
  • 地址ID增加:这发生的原因是在第一个会话中将标识符分配给对象的 flush() 。但这并不是对先前 Address 的更新,而是对新 AddressID 分配。

This cannot be seen in your code, but I assume that the code that is executed twice is also executed within two different sessions. This would explain all the side effects you observe:

  • only one address: because second session is not aware of the first one (not commit-ed)
  • address ID is increased: this happens because of flush() in the first session where the identifier is assigned to the object. This is not an update to the previous Address though, but rather an ID assignment to the new Address.
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文