结合SQLAlchemy核心和ORM get问题

2024-06-14 13:56:43 发布

您现在位置:Python中文网/ 问答频道 /正文

如何组合SQLAlchemy的两个组件——Core(SQL表达式)和ORM? 我有一些使用ormmapper的表,而其他的只是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()的日志显示它只更新了一次(注=None),第二次更新丢失了吗?在

^{pr2}$

更新第二个问题解决。
感谢@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

Tags: infononeidbaseparamsqlalchemysessionmytable
1条回答
网友
1楼 · 发布于 2024-06-14 13:56:43

在阅读了更多关于session的文章后,我有了答案。在


session有其工作机制,一是{}

"All changes to objects maintained by a Session are tracked - before the database is queried again or before the current transaction is committed, it flushes all pending changes to the database. This is known as the Unit of Work pattern." http://docs.sqlalchemy.org/en/latest/orm/session_basics.html

  • 第一个问题是由于unit of work,因此SQLAlchemy将跟踪更改的内容,并且只聪明地只执行真正需要的操作。结果是只需要一次更新。

  • 第二个问题通过手动session.flush()ORM更新来获得正确的执行顺序来解决。因为我使用了SQLAlchemy的两个独立机制,unit of work似乎也不适用于原始SQL表达式。

相关问题 更多 >