一般动作
登录
Wiki: BROPEN ▼: Document Index
»
Space: FAQ ▼: Document Index
»
Page: 为什么调用 Domain.current().applications 会抛出 LazyInitializationException 异常
搜索
zh
页面动作
导出 ▼: 以PDF格式导出 以RTF格式导出 以HTML格式导出
更多动作 ▼: 打印预览 察看源码
欢迎进入Wiki » FAQ » 为什么调用 Domain.current().applications 会抛出 LazyInitializationException 异常?

# 为什么调用 Domain.current().applications 会抛出 LazyInitializationException 异常?

在2013-11-13 09:00上被李小翔修改
评论 (0) · 附件 (0) · 记录 · 信息

问题代码：

import bropen.framework.core.security.Domain;
// 获得当前管理域
Domain domain = Domain.current()
// 使用当前域下的所有应用进行查询，会抛出异常！！
ProcessDefinition.findAllNotDisabledByApplicationInList(domain.applications, [cache:true])

抛出异常：

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role:
bropen.framework.core.security.Domain.applications, no session or session was closed
... 13 more

在错误日志上加上 withTransaction 或者 withNewSession 都不管用，该如何处理呢？

其原因在于，bropen.framework.core.security.Domain.current()（包括DomainApplication.current()）拿到的实体Bean都是来自缓存，而这些缓存可能是早在被其他代码（比如BootStrap）调用时生成的，当时的Hibernate Session早已关闭，如果通过这些Bean去获得关联的其他实体对象，肯定会抛出no session or session was closed异常。

知道原因后，解决问题就很容易了，可以采用两种方式来处理：

1. 通过获得实体对象后，调用 attach 方法将对象附加到当前的Hibernate Session中，代码如：

if ( !bean.isAttached() ) {
bean.attach()
}

这种处理方式适用与多数类似的异常，但是如果这个bean可能同时被多个线程调用，这样做会不会导致线程不安全的情况发生呢（细心的读者可以验证一下）。

因此，比较偷懒的做法是采用下面的方案2来规避这个问题。

2. 接受这个bean游离在当前Hibernate Session之外的现实，通过其他手段来获取关联的其他实体对象，就最上面的问题代码来说，改造如下：

import bropen.framework.core.security.Domain;
import bropen.framework.core.security.DomainApplication;
// 从缓存中获得当前管理域对象
Domain domain = domain.current();
// 加一行，避免session关闭问题
List<DomainApplication> apps = DomainApplication.findAllByDomain(domain);
// 这回就不会异常了
ProcessDefinition.findAllNotDisabledByApplicationInList(apps, [cache:true]);

当然，为什么不把关联的 applications 也缓存下来呢？

呵呵，那缓存的工作量就比较大了，整个系统的数据结构都有可能相互关联，谁也无法预料到二次开发时中会如何调用，这样做意义并不大；而且，如果关联的对象发生了变化，还得通知缓存进行更新......

类似的，如果碰到类似的异常，也可以采用相同的方法处理。

标签： grails hibernate BroFramework
在2013-11-13 08:59上被李小翔创建

- 评论 （0）
- 附件 （0）
- 记录
- 信息

# 快速链接

- 首页
- 新闻动态
- FAQ

Copyright © 2013 北京博瑞开源软件有限公司
京ICP备12048974号