会话中存储的域对象正在变得分离



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

尝试从会话中存储的域对象访问字段时,我们正在获得间歇性LazyInitializationException

澄清流程的工作原理:

我们有一个过滤器(http://docs.grails.org/2.5.4/ref/ref/plug-ins/filters.html),该过滤器在每个控制器操作之前都会被调用。在此过滤器中,我们将一个域对象存储在会话(http://docs.grails.org/2.5.4/ref/servlet api/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

因此,出于某种原因,休眠会话在请求完成之前已关闭,因此懒惰的负载异常。

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

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

问题是,我不知道为什么,并且想了解为什么在应用程序的其他部分盲目实施此解决方案之前,这解决了问题。我没有理由为什么该对象应与冬眠会话分离,因为此流程全部发生在同一请求中。最重要的是,这是一个非常随机的问题 - 大概发生了该请求的时间的1%,即使不是更少。

要澄清,问题是;为什么会话要关闭,为什么当对象全部发生在同一请求范围内时,为什么该对象会与冬眠会话分离?另外,为什么它只会很少发生?

你好,这发生了,因为懒惰模式只会缓存域的第一个级别,因此,当您尝试访问另一个字段时,会给您带来此错误,并且默认的获取模式通常是懒惰的,我会这样保留,并像你一样这样做,帐户帐户= account.findbyid(session.account.id)

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

最新更新