postgresql - 使用 session.query(cls).from_statement 多次插入“on conflict ...返回*”在提交之前不会反映更改
问题描述
我正在使用带有 postgres 11 的 sqlalchemy 1.3.0。我正在尝试使用INSERT
withON CONFLICT DO UPDATE ... RETURNING *
来创建我的模型的实例。
class Model(Base):
__tablename__ = 'mytable'
pk = Column(String(64), primary_key=True)
col2 = Column(String(64))
@classmethod
def upsert(cls, pk, col2, session):
return session.query(cls).from_statement(
text(
"""
INSERT INTO {} (pk, col2) VALUES (:pk, :col2)
ON CONFLICT (pk) DO UPDATE SET col2=EXCLUDED.col2 RETURNING *;
""".format(cls.__tablename__)
)
).params(pk=pk, col2=col2).one()
obj1 = Model.upsert(1, 'one', session)
obj2 = Model.upsert(1, 'two', session)
print(obj2.col2) ----> outputs "one"
session.commit()
print(obj2.col2) ----> outputs "two"
第二个 upsert 确实向数据库发出了正确的命令,但是打印返回对象的 col2 属性会显示在第一个 upsert 期间插入的列的值。然后,如果我执行 a session.commit()
,对象会神奇地更新以显示新值。我错过了什么?我希望从函数返回的对象反映行更新到的值,而不必进行提交,因为我希望这与其他几件事一起在事务中发生。
解决方案
事实证明,session.commit()
本质上是使对象过期,因此以下内容print(obj2.col2)
将重新查询数据库以填充其属性。
为了使 obj2.col2 成为正确的值而不提交(并重新查询数据库),我只需要session.expunge(obj1)
在第二次 upsert 调用之前执行创建 obj2。
推荐阅读
- javascript - 如何从 Firebase 检索多条数据并将其附加到不同的做同样的事情?
- excel - VBA 用户表单复选框跟踪
- mysql - 在sql中计算运行比率
- javascript - 在 nodejs 中停止已启动的脚本
- feature-engineering - Vowpal Wabbit:关于交互特征权重的问题
- python - 有没有办法通过将其他 2 列分组到相同的值上来对 2 列求和?
- node.js - 如何停止 Apollo-Server
- java - 使用 Selenium 和 TestNG 在 IntelliJ 中运行测试时“未找到测试”
- javascript - 将 xml 解析为 javascript 中的字典或字典数组
- android - 当第二个应用程序运行时,GPS 高度的波动停止