SQLAlchemy 的 session.query(...).all()居然会把还没 commit 的对象 flush 到数据库?

2017-01-21 05:39:34 +08:00
 eyp82
创建了一个 object, 以及把其加入到 session 里后, 查询 id 都是空, 但是执行了一次 query 之后 id 就有值了.

感觉这么处理很怪, 一个 query 语句居然会背地里对数据库做修改. 不太理解为什么要这样设计. 我觉得把修改数据库的动作放到session.add()里不是更好? query我默认就是不对数据库做修改的啊.


----------
解释一下下面的输出: User是一个类, 代表一张表, session是我创建的Session类的对象.
1. 创建一行数据(User的实例)
2. 调用session.add()加入到session
3. 查询: session.query(...).all()

------------------------
>>> user7 = User(name='test', fullname='test_full', password='nopwd')
>>> user7.id
>>> session.add(user7)
>>> user7.id
>>> session.query(User).all()
2017-01-20 16:37:00,557 INFO sqlalchemy.engine.base.Engine INSERT INTO users (name, fullname, password) VALUES (?, ?, ?)
2017-01-20 16:37:00,557 INFO sqlalchemy.engine.base.Engine ('test', 'test_full', 'nopwd')
2017-01-20 16:37:00,557 INFO sqlalchemy.engine.base.Engine SELECT users.id AS users_id, users.name AS users_name, users.fullname AS users_fullname, users.password AS users_password
FROM users
2017-01-20 16:37:00,558 INFO sqlalchemy.engine.base.Engine ()
[...deleted...]
>>> user7.id
8
>>>
4652 次点击
所在节点    Python
8 条回复
halmstad
2017-01-21 07:53:31 +08:00
首先,并没有提交到数据库,只 flush 了, flush 和 commit 不是一件事情。其次 session 创建的时候有个 auto_flush 参数表明 query 的时候是否 flush ,默认是 True, 多看看文档,才能更好的使用
panyanyany
2017-01-21 08:03:17 +08:00
在 SQLAlchemy 中, add() 操作之后数据成为 pending 状态,此时数据不会立即写入到数据库中。
当你执行 query() 的时候,它会先把之前状态为 pending 的数据写入到数据库,并且更新当前 session 中存储的数据,然后再执行 query()
你可以看下文档的这个小节:
[Adding and Updating Objects]( http://docs.sqlalchemy.org/en/rel_1_1/orm/tutorial.html#adding-and-updating-objects)
jjx
2017-01-21 08:11:40 +08:00
处理是合理的,只是不太智能,对同一个对象会生成多条更新语句.性能敏感时建议直接用 sql expression
rogwan
2017-01-21 08:26:36 +08:00
和 return 返回自动提交类似,也算是一种防止用户忘记 commit 的做法吧。

默认主动帮用户提交、默认不主动帮用户提交,两个方案肯定是选前者。
eyp82
2017-01-21 08:34:02 +08:00
@halmstad 是没有 commit, 毕竟后面还可以 rollback. 我的意思是确实执行了写操作, 否则那个 auto_increment 的 id 是拿不到的(这个必须数据库生成并返回, ORM 不能自作主张生成一个) 而这个放在 query 里做, 感觉不如放到前面 add 里.
eyp82
2017-01-21 08:34:56 +08:00
@halmstad 又看了一下我的帖子, 可能是我的标题有些误导.
skydiver
2017-01-21 13:28:29 +08:00
正常行为,要不然你后面需要用这个 id 怎么办
sleshep
2017-01-22 17:51:57 +08:00
一般中间 query 的时候都会手动 flush,这是常识

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/335990

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX