hibernate 为集合属性配置延迟加载时的问题,牛人进!

youjianbo_han_87 2009-09-10 10:59:56
首先请看清楚,不要没看清楚就回答!

将 <set name="empAnnualVactions" inverse="true" lazy="true" 会报下面的错误

org.hibernate.LazyInitializationException: failed to lazily initialize a collection of role ********* no session or session was closed

我不想问怎么解决,网上太多太滥的方法了,无非是将 lazy 设为 false。但是我就是想集合属性延迟加载呀。

其实在 set里 加上 fetch = "join",也可以解决。

我想问的是, 出现 这种问题的根本原因是什么,是将 fetch ="select" 的原因吗?

我看了下 fetch ="select" 的意思是说,他会先将 主表全部查询出来,然后在用 主表 关联字段 去取关联类。和 fetch ="join" 一句关联查询,只是效率上的差别吧。
...全文
219 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
will_lp 2010-06-12
  • 打赏
  • 举报
回复
仅仅设置lazy=“true”,延迟加载等于没有加载;加上fetch=“join”:Hibernate通过 在SELECT语句使用OUTER JOIN(外连接)来获得对象的关联实例或者关联集合,加上和lazy=“false”一样;查询抓取(Select fetching) fetch=“select”,另外发送一条 SELECT 语句抓取当前对象的关联实体或集合.除非你显式的指定lazy="false"禁止延迟抓取(lazy fetching),否则只有当你真正访问关联关系的时候,才会执行第二条select语句;
youjianbo_han_87 2009-09-17
  • 打赏
  • 举报
回复
一番折腾,总能明白一些东西,结贴给分,生命在于折腾
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 3 楼 youjianbo_han_87 的回复:]
例如,对于parent.getChildren()这样一个方法来说,parent对象是一开始就通过Hibenate对象拿到的,但是由于 <one-to-many>的lazy属性设置为false,在get parent这个对象时候,并没有拿到其children。当真正用到children的时候,此时的parent已经变成托管状态的了,在托管态的对象是无法再次使用级联操作的。
所以另外一种解决就是重新关联parent到session,然后执行一下getChildren(),当parent再次变成托管状态时,就不会出错了。

重新获得一个session,然后利用session.update(parent),将其重新关联,变成持久态。在执行一下parent.getChildren()。
这里需要注意另外一个问题,update时,会不会出现级联更新?
[/Quote]

可我看见过别人配的程序,没有这么麻烦,也没有将 fetch 设为 'join',就是和我报错时一样配的,程序里面也没有什么和sessoin再关联一次这样的,可是人家的不会报错,人家现在不在公司了。
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
例如,对于parent.getChildren()这样一个方法来说,parent对象是一开始就通过Hibenate对象拿到的,但是由于<one-to-many>的lazy属性设置为false,在get parent这个对象时候,并没有拿到其children。当真正用到children的时候,此时的parent已经变成托管状态的了,在托管态的对象是无法再次使用级联操作的。
所以另外一种解决就是重新关联parent到session,然后执行一下getChildren(),当parent再次变成托管状态时,就不会出错了。

重新获得一个session,然后利用session.update(parent),将其重新关联,变成持久态。在执行一下parent.getChildren()。
这里需要注意另外一个问题,update时,会不会出现级联更新?
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
楼上的没有回答我的问题,为什么我将 fetch配置成 fetch = "join"就不会报错。照楼上的说。这样配了,session 就 开启了?其次,我没有将 对象放置到SESSION --这个是WEB SESSION。
APOLLO_TS 2009-09-10
  • 打赏
  • 举报
回复
SESSION 开启
事务开启
获得实例对象---如果你将该对象放置到SESSION --这个是WEB SESSION,那么这个对象关联的集合有可能是没有初始化,因为配置了延迟加载。但是在这个小区域内关联对象是可以获得的。因为这要执行两次查询。
事务关闭
SESSION关闭

当SESSION关闭后,你用获得的实例是不能在获得关联对象的。

所谓的延迟加载是在当前连接中需要使用才进行查询。

像页面使用关联对象是使用了OSIV-模式。连接关闭基本是在页面解析完成以后。

youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 archko 的回复:]
如果回答两次是一种错,那回答三次可以算不可原谅了.
延迟加载,在配置文件里就可以配置的.但你要加载东西就必须要有SESSION,所以你说的是不可能的.
可能你看到你你以前的同事的代码有些没有看清楚(猜想)....
如果你是砖家,随便扔.我想成为砖家
[/Quote]

我不用砖头拍你,我是来商量的,嘿嘿,言归真传吧,我取数据的时候,session没有关闭。
archko 2009-09-10
  • 打赏
  • 举报
回复
如果回答两次是一种错,那回答三次可以算不可原谅了.
延迟加载,在配置文件里就可以配置的.但你要加载东西就必须要有SESSION,所以你说的是不可能的.
可能你看到你你以前的同事的代码有些没有看清楚(猜想)....
如果你是砖家,随便扔.我想成为砖家
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
麻烦回答问题时,看看我的题目里面的内容。怎么解决我早知道了,不需要贴出来解决办法了。

to:15 楼 看清楚,可能你只看了部分帖子。
long5281 2009-09-10
  • 打赏
  • 举报
回复
web.xml

<filter-name>hibernateFilter</filter-name>
<filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class>
<init-param>
<param-name>singleSession</param-name>
<param-value>false</param-value>
</init-param>
</filter>

<filter-mapping>
<filter-name>hibernateFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

long5281 2009-09-10
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 xiechunmei13 的回复:]
以前也遇到过。
一开始怎么都不理解。
我没有像楼主那样的配置。
我是在页面以开始就加载一个下拉框。
是自己中间的逻辑出了问题,导致session会话提前关闭掉了。
如果不是自己逻辑上的问题。那么可以在web。xml中配置 
<!-- 延迟会话到view界面后在关闭-->
<filter>
<filter-name>openSession </filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openSession </filter-name>
<url-pattern>/* </url-pattern>
</filter-mapping>


[/Quote]

这个就是表示SESSION单独业务处理,业务处理后不直接关闭.
archko 2009-09-10
  • 打赏
  • 举报
回复
不可能,fetch是抓取策略,和这个无关,
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
楼上的没有仔细看我的问题。忽略你的回答。
xiechunmei13 2009-09-10
  • 打赏
  • 举报
回复
以前也遇到过。
一开始怎么都不理解。
我没有像楼主那样的配置。
我是在页面以开始就加载一个下拉框。
是自己中间的逻辑出了问题,导致session会话提前关闭掉了。
如果不是自己逻辑上的问题。那么可以在web。xml中配置
<!-- 延迟会话到view界面后在关闭-->
<filter>
<filter-name>openSession</filter-name>
<filter-class>
org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
</filter-class>
</filter>
<filter-mapping>
<filter-name>openSession</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>

其次的解决方法也是最不推荐的解决方法就是在hbm文件中lazy=fase
已般不到万不得已不建议在这里做更改。
具体当时我的逻辑哪里问题我也忘了。一年前学习中遇到的了。所以给不了楼主好的解释了。抱歉。

总共三种解决方法:1,检查逻辑。2:web.xml 3:hbm lazy=fase
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
用 Hibernate.initialize方法可以。但是想在配置里面就搞定。
archko 2009-09-10
  • 打赏
  • 举报
回复
这个问题主要是SESSION关闭了,其实我觉得 延迟并不怎样.似乎没有什么用处,
在关联时配置一对多,多对一.你取得一个不马上取它相关的集合或一个对象.通常是设TRUE.
那怎么解决你的问题呢?
比如:parent,children
你取得了一个parent,lazy=true,这时不马上取children
但你去要在页面上显示children,你觉得可以么?当然不行了,肯定是要再查询一次才有东西,但这时是延迟的,你想要它自动查,所以出错了.
那如果不是自动查呢?比如我一个操作,需要同时取得parent和它的children,那就可以强制初始化这个children
好像是initialize(parent.getChildren()),这样,配置文件还是延迟的,只对你这个操作可以加载它的children.
而其它的操作还是延迟的.
查出children然后要它的parent也是这样的,通常树结构就有这个,当然你可以设为false就不是延迟加载了.
youjianbo_han_87 2009-09-10
  • 打赏
  • 举报
回复
忽略 8,9楼的回答,没有认真看。

to: APOLLO_TS

request->session open--->逻辑操作--->session close--->response 这个步骤。

你的意思是说 做完一次读取操作,session会自动关闭??????

feishare 2009-09-10
  • 打赏
  • 举报
回复
要使用open session in view吧,spring实现了这个filter
qsrock 2009-09-10
  • 打赏
  • 举报
回复
呵呵!你session都关闭了还加载什么啊??
你要写个过滤器之类的东西让你的session继续处于开启状态
APOLLO_TS 2009-09-10
  • 打赏
  • 举报
回复
你看我第一次回复的最后一句话。你如果理解,那么别人配置那么简单就很容易理解了。

request->session open--->逻辑操作--->session close--->response

加载更多回复(2)

67,512

社区成员

发帖
与我相关
我的任务
社区描述
J2EE只是Java企业应用。我们需要一个跨J2SE/WEB/EJB的微容器,保护我们的业务核心组件(中间件),以延续它的生命力,而不是依赖J2SE/J2EE版本。
社区管理员
  • Java EE
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧