session--过期刷新

过期/刷新

使用 Session 时经常出现的一个重要考虑因素是处理已从数据库加载的对象上存在的状态,以使它们与事务的当前状态保持同步。 SQLAlchemy ORM 基于身份映射的概念,这样当从 SQL 查询“加载”对象时,将维护一个与特定数据库身份相对应的唯一 Python 对象实例。 这意味着如果我们发出两个单独的查询,每个查询都针对同一行,并返回一个映射对象,这两个查询将返回相同的 Python 对象:

u1 = session.query(User).filter(id=5).first()
u2 = session.query(User).filter(id=5).first()
u1 is u2

此后,当 ORM 从查询中取回行时,它将跳过已加载对象的属性填充。 这里的设计假设是假设一个事务完全隔离,然后在事务不隔离的程度上,应用程序可以根据需要采取步骤从数据库事务中刷新对象。

当一个 ORM 映射对象被加载到内存中时,通常有三种方法可以用当前事务中的新数据刷新其内容:

  • expire() 方法 - Session.expire() 方法将删除对象的选定或所有属性的内容,以便下次访问时从数据库加载它们,例如 使用延迟加载模式:
session.expire(u1)
u1.some_attribute  # <-- lazy loads from the transaction
  • refresh() 方法 - 密切相关的是 Session.refresh() 方法,它完成 Session.expire() 方法所做的所有事情,但也会立即发出一个或多个 SQL 查询以实际刷新对象的内容:
session.refresh(u1)  # <-- emits a SQL query
u1.some_attribute  # <-- is refreshed from the transaction
  • populate_existing() 方法 - 这个方法实际上是在 Query 对象上作为 Query.populate_existing() 并指示它应该返回无条件地从数据库中的内容重新填充的对象:
u2 = session.query(User).populate_existing().filter(id=5).first()

关于刷新/过期概念的进一步讨论可以在刷新/过期中找到。

我正在使用我的 Session 重新加载数据,但它没有看到我在其他地方提交的更改

关于这种行为的主要问题是会话表现得好像事务处于可序列化隔离状态,即使它不是(通常不是)。实际上,这意味着会话不会更改已在事务范围内读取的任何数据。

如果对“隔离级别”这个词不熟悉,那么您首先需要阅读此链接:

隔离级别

简而言之,可序列化隔离级别通常意味着一旦您在事务中选择了一系列行,每次重新发出该 SELECT 时,您将获得相同的数据。如果您处于下一个较低的隔离级别“可重复读取”,您将看到新添加的行(并且不再看到已删除的行),但对于您已经加载的行,您将看不到任何更改。仅当您处于较低的隔离级别时,例如“读已提交”,是否可以看到一行数据更改其值。

有关在使用 SQLAlchemy ORM 时控制隔离级别的信息,请参阅设置事务隔离级别/DBAPI AUTOCOMMIT。

为了显着简化事情,Session 本身根据完全隔离的事务工作,并且不会覆盖它已经读取的任何映射属性,除非你告诉它。尝试重新读取您已经在正在进行的事务中加载的数据的用例是一个不常见的用例,在许多情况下没有效果,因此这被认为是例外,而不是常态;为了在此异常中工作,提供了几种方法来允许在正在进行的事务的上下文中重新加载特定数据。

当我们谈论 Session 时,要理解我们所说的“事务”是什么意思,您的 Session 旨在仅在事务中工作。管理事务中对此进行了概述。

一旦我们弄清楚了我们的隔离级别是什么,并且我们认为我们的隔离级别设置在足够低的级别,这样如果我们重新选择一行,我们应该在我们的 Session 中看到新数据,我们如何看到它?

三种方式,从最常见到最少:

我们只需通过调用 Session.commit() 来结束我们的事务并在下次访问 Session 时启动一个新事务(请注意,如果 Session 处于较少使用的“自动提交”模式,则会调用 Session.begin( )以及)。绝大多数应用程序和用例都没有无法“看到”其他事务中的数据的任何问题,因为它们坚持这种模式,这是短期事务最佳实践的核心。请参阅何时构建 Session、何时提交以及何时关闭它?对此的一些想法。

我们告诉我们的 Session 重新读取它已经读取的行,或者当我们下次使用 Session.expire_all() 或 Session.expire() 查询它们时,或者立即使用刷新在对象上。有关这方面的详细信息,请参阅刷新/过期。

我们可以运行整个查询,同时使用“填充现有”将它们设置为在读取行时绝对覆盖已加载的对象。这是 Populate Existing 中描述的一个执行选项。

但是请记住,如果我们的隔离级别是可重复读取或更高,则 ORM 无法看到行中的更改,除非我们启动一个新事务。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值