Session(会话)
- 你可以把数据库会话 (
Session
) 想象成一个 缓存区 或 临时草稿区。当你创建、修改或删除模型对象时,这些操作首先只是发生在内存中的这个“临时工作区”里,并没有立即影响到实际的数据库。 - 对象的容器:存放着你从数据库取出的对象(
identity_map
)和你新创建待存入的对象(new
)。 - 变更跟踪器:它跟踪所有被管理对象的任何状态变化(例如你修改了
hero.age
),并记住这些待执行的更改(存放在dirty
,deleted
等集合中)。 - 事务管理器:它封装了一个数据库事务,
commit()
和rollback()
让你可以原子性地接受或拒绝所有更改。 - 数据库抽象接口:它提供了
get()
,exec()
等方法,让你无需编写原始SQL即可与数据库交互。 - SQLModel 中的
session
对象(实际上是sqlalchemy.orm.Session
)功能非常丰富,它是所有数据库交互的核心。它提供了一整套用于管理数据库会话、事务和对象状态的方法和属性。
1. 核心生命周期管理(最重要的功能)
add(instance) | 将一个对象计划插入数据库或将其加入当前会话的管理。 | 这是“加入购物车”操作,对象状态变为 pending 。 |
add_all(instances) | 将一个对象列表(如 [hero1, hero2] )全部加入会话。 | 批量版的 add() 。 |
commit() | 提交当前事务,将所有暂存的更改(增删改)永久保存到数据库。 | 这是“点击下单”操作,是数据持久化的关键一步。 |
flush() | 刷写Session,将SQL语句发送到数据库执行,但不提交事务。 | 提交前的中间步骤,常用于获取数据库生成的ID(需结合refresh )。 |
refresh(instance) | 从数据库中重新加载一个对象的所有属性。 | 提交后获取自增ID,或确保对象状态与数据库一致。 |
expunge(instance) | 将对象从当前Session的管理中移除。 | 此后对该对象的更改不会被Session跟踪。 |
close() | 关闭Session,结束所有事务性资源(如数据库连接)。 | 会回滚所有未提交的更改。通常用 with 语句自动管理。 |
当你调用 commit()
时,Session 会执行以下操作:
- 刷新 (Flush):将 Session 中累积的所有指令(SQL 语句)一次性发送到数据库服务器。
- 提交事务 (Commit Transaction):告诉数据库:“我刚刚发给你的这些指令,现在请正式执行它们,并让这些更改永久生效。” 数据库会真正执行这些 SQL 语句(
INSERT
,UPDATE
,DELETE
)。 - 结束事务:完成当前的事务。提交后,Session 会开始一个新的事务环境。
- 如果你只是
add
或修改了对象,但没有调用commit()
,那么当你关闭程序或 Session 时,所有暂存的更改都会丢失。数据库里的数据不会有任何变化。
在调用 commit()
之后,你经常会看到 session.refresh(hero)
。它的作用是让数据库重新加载该对象的最新状态。
为什么需要这个?因为当你插入一条新记录时,数据库可能会设置一些默认值或者生成自增ID。这些值是在数据库服务器端生成的。refresh()
会从数据库拉取这些新生成的数据,并更新你的 Python 对象,让你能立即访问到它们(比如新生成的 hero.id
)。
2. 查询功能(读取数据)
get(entity, ident) | 根据主键快速获取一个对象。 | 如 session.get(Hero, 1) 。最常用的精准查询。 |
exec(statement) | 执行一个SQLModel select 语句,返回结果。 | 这是执行复杂查询的核心方法,如 session.exec(select(Hero)) 。 |
query(Model) | (传统SQLAlchemy风格,SQLModel更推荐exec(select(...)) ) | 构建查询的老式方法,但功能强大。 |
3. 删除功能
delete(instance) | 计划删除一个对象。 | 将对象状态标记为 deleted ,等待 commit() 后从数据库真正删除。 |
4. 事务控制(高级但重要)
5. 状态检查(用于调试和理解)
总结
session
提供了一套完整的ORM(对象关系映射)会话管理机制。对于初学者,最关键的是掌握:
官方文档是查询所有方法和属性的最佳场所。在编程时,你的IDE(如VS Code, PyCharm)的自动补全功能也是探索 session
功能的好帮手。
- **
add()
** -> 把对象放入Session - **
get()
** -> 按主键取对象 - **
exec(select(...))
** -> 执行复杂查询 - **
delete()
** -> 标记删除对象 - **
commit()
** -> 最终保存所有更改 - **
rollback()
** -> 撤销所有未保存的更改 - ** refresh()** -> 让数据库重新加载该对象的最新状态。