【问题标题】:Domain object stored in session is becoming detached存储在会话中的域对象正在分离
【发布时间】:2017-04-21 00:14:20
【问题描述】:

我在生产环境中部署了一个 Grails 应用程序 (2.5.4),它接收大量流量。

在尝试访问存储在会话中的域对象中的字段时,我们遇到了间歇性的 LazyInitializationException 异常。

阐明流程的工作原理:

我们有一个过滤器 (http://docs.grails.org/2.5.4/ref/Plug-ins/filters.html),它在每个控制器操作之前被调用。在这个过滤器中,我们在会话 (http://docs.grails.org/2.5.4/ref/Servlet%20API/session.html) 中存储一个域对象,如下所示:

session.account = Account.get(1)

在控制器中,我们像这样检索域:

def account = session.account

然后我们将域对象传递给另一个服务,该服务调用另一个服务,该服务最终尝试调用域对象上的 hasMany 字段,如下所示:

account.transactions.name

上面会抛出一个LazyInitializationException,并带有类似这样的消息:

failed to lazily initialize a collection of role: com.example.app.Account.transactions, no session or session was closed

因此,由于某种原因,Hibernate 会话在请求完成之前被关闭,因此出现延迟加载异常。

我们发现在控制器中执行以下操作完全消除了错误的发生:

Account account = Account.findById(session.account.id)

问题是,在盲目地在应用程序的其他部分实施此修复之前,我不知道为什么并且想了解为什么这会解决问题。我看不出为什么该对象应该与 Hibernate Session 分离,因为这个流程都发生在同一个请求中。最重要的是,这是一个非常随机的问题——它可能会出现在请求发出的 1% 的时间里,如果不是更少的话。

为了澄清,问题是;为什么会话被关闭,为什么当对象都发生在同一个请求范围内时,它会与 Hibernate 会话分离?另外,为什么它只是非常罕见且随机地发生?

【问题讨论】:

  • 在尝试访问account.transactions 之前,您是否尝试过使用account.attach()?见docs.grails.org/latest/ref/Domain%20Classes/attach.html
  • 嘿 - 我没有特别尝试过,但我想它会像 Account account = Account.findById(session.account.id) 一样工作。我的问题不是如何将域重新附加到会话,因为这很容易,而是为什么它首先被分离。您提供的链接中的文档指出:“如果从 Session 中检索到一个对象并将其放入诸如 HttpSession 之类的 Web 范围内,那么一旦 Session 关闭并丢弃,它将与 Hibernate Session “分离”。那么,如果请求没有完成,为什么会话会关闭并丢弃?
  • Grails 有一个 Slack 频道,专家们往往会在那里闲逛。 StackOverflow 更适合“如何...”问题,所以我认为你会在 Slack 或 Grails 邮件列表中取得更好的成功。
  • 谢谢 - 我已经在 slack 频道问过了。如果我得到回复,我会报告。

标签: spring hibernate grails lazy-loading httpsession


【解决方案1】:

您好,这是因为惰性模式只会缓存域的第一级,所以当您尝试访问其他字段时会出现此错误,并且默认获取模式通常是惰性的,我会保持这样并执行正如你正在做的, 账户帐号 = Account.findById(session.account.id)

因为根据另一方列表的大小,将所有内容都放入会话中对您的系统根本没有好处。

【讨论】:

  • 我知道域正在使用延迟加载,但如果 Hibernate Session 仍然打开,那么它应该能够获取域的任何更高级别的关系。那么问题来了,为什么休眠会话会随机关闭,为什么域对象在请求还没有结束的情况下会分离?
猜你喜欢
  • 2017-08-25
  • 2017-12-06
  • 2012-01-26
  • 2014-01-17
  • 2010-11-08
  • 1970-01-01
  • 2023-03-09
相关资源
最近更新 更多