【发布时间】:2017-02-11 15:06:51
【问题描述】:
如何结合 SQLAlchemy 的两个组件——核心(SQL 表达式)和 ORM ? 我有一些使用 ORM 映射器的表,而其他的只是 Table 对象,我想要 一个连接和一个事务处理两个。
我有以下两个示例,但遇到了问题(结果与我交叉两种访问方式的查询不一致)。 一个使用自动提交会话,另一个使用默认会话。
session_autocommit=Session(bind=db,autocommit=True)
def f():
with session_autocommit.begin() as trans:
# ORM
x=session_autocommit.query(Mytable).filter(Mytable.id==1).first()
# sql expression by SQLAlchemy Core
session_autocommit.execute(mytable.update().where(mytable.c.id==1)\
.values(note=None))
# update via ORM
x.note='a'
f() # ok two update appear in log.
f() # ! only one update as below
x.note == 'a'
# the second run of f() returns False but should be True.
f() 第二次运行的日志说它只有一次更新 (note=None) ,第二次更新错过了?
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id, mytable.note AS mytable_note
FROM mytable
WHERE mytable.id = %(id_1)s
LIMIT %(param_1)s
INFO sqlalchemy.engine.base.Engine {'param_1': 1, 'id_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(id_1)s
INFO sqlalchemy.engine.base.Engine {'id_1': 1, 'note': None}
INFO sqlalchemy.engine.base.Engine COMMIT
UPDATE第二个问题解决了。
感谢@univerio 的评论,我需要先flush 它才能正确执行执行顺序。由于我使用的是两个独立的 SQLAlchemy 机制。
session=Session(bind=db,autocommit=False)
# default session must rely commit to control transaction.
session.commit()
x=session.query(Mytable).filter(Mytable.id==1).first()
x.note='a'
session.execute(mytable.update().where(mytable.c.id==1)\
.values(note=None))
session.commit()
x.note=='a'
# the test return True but should be None.
日志说两次更新的顺序不同?
INFO sqlalchemy.engine.base.Engine COMMIT
INFO sqlalchemy.engine.base.Engine BEGIN (implicit)
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id, mytable.note AS mytable_note
FROM mytable
WHERE mytable.id = %(id_1)s
LIMIT %(param_1)s
INFO sqlalchemy.engine.base.Engine {'id_1': 1, 'param_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(id_1)s
INFO sqlalchemy.engine.base.Engine {'note': None, 'id_1': 1}
INFO sqlalchemy.engine.base.Engine SELECT mytable.id AS mytable_id
FROM mytable
WHERE mytable.id = %(param_1)s
INFO sqlalchemy.engine.base.Engine {'param_1': 1}
INFO sqlalchemy.engine.base.Engine UPDATE mytable SET note=%(note)s WHERE mytable.id = %(mytable_id)s
INFO sqlalchemy.engine.base.Engine {'note': 'a', 'mytable_id': 1}
INFO sqlalchemy.engine.base.Engine COMMIT
【问题讨论】:
-
我无法重现您的第一个案例。第二种情况是预期的,因为刷新是随着提交发生的;如果您在
x.note = 'a'之后执行session.flush(),您将获得预期的结果。 -
感谢@univerio ,已编辑,第一种情况的问题是在第二次重复运行后发生的。
标签: python sql orm sqlalchemy relational-database