克服懒惰初始化异常和性能问题的困境

时间:2013-12-13 06:33:51

标签: java hibernate struts2

在休眠状态下,@ManyToOne关系几乎不会产生任何问题,因为默认提取类型非常渴望。

但是,我们在@OnetoMany端遇到了严重问题。当我们尝试获取集合时,抛出'LazyInitializationException:无法初始化代理',因为默认的提取类型对于一对多是惰性的。

在这种情况下,我们要么设置:

  • @LazyCollection(LazyCollectionOption.FALSE)虽然可以解决问题,但是当有大量记录时,它会显着降低性能。

  • 获取模式:左连接,但它显示org.hibernate.HibernateException:无法同时获取多个包

据我所知,hibernate提出了几种克服这个问题的机制:

  • 选项1

    • 指定@IndexColumn而不是LazyCollectionOption.FALSE。作为一项成果,确定了以下行为,这些行为也会影响绩效:

    • 使用各个实体(@OnetoMany)的主键创建临时表。因此,当存在许多“一对多”关系时,会为每个关系创建临时表。

  • 选项2

    • 将集合的数据类型从List更改为Set。这导致Struts 2在前端出现问题,因为Set是基于索引的集合,因为我们需要以迭代方式动态添加记录。

    • 为了克服这个问题,我们将利用DTO来捕获UI输入。通过在DTO中设置集合类型List并在'domain'中设置,并通过汇编程序,我们将从ListSet(DTO→域)进行所需的转换,反之亦然。

选项2中提到的决议是否可行?如果没有,请提供建议和反馈。

2 个答案:

答案 0 :(得分:0)

根据我的经验,您通常只有一两个地方需要急切初始化(例如:在“记录详细信息”视图中)。对于这种情况,懒惰将始终如此,除了需要急切的几个地方之外,还有一个名为"Fetch profile"的Hibernate功能。这是一个相对较新的功能,不是很有名,但它非常强大,在这种情况下可能有所帮助。

不幸的是,这还没有在JPA中,这意味着你需要在你原本干净的JPA代码中添加一些专有的Hibernate部分,但这是一个很低的代价,IMO。

答案 1 :(得分:0)

如果您尝试访问一对多属性或集合中的对象并且此时没有打开的会话,则会引发LazyInitializationException。默认情况下,该关联是为延迟初始化而设计的,这是性能问题的好方法,可以根据需要初始化一对多属性。唯一的问题是会话状态。为此,Hibernate强加了Open Session In View模式。您可以使用自定义拦截器手动实现它,也可以通过Full Hibernate Plugin for Struts2实现。了解这个插件如何与他们的showcase中的Struts2 jQuery Grid插件一起使用。