java - Hibernate 问题 : org. hibernate.LazyInitializationException:无法初始化代理 - 无 session

标签 java hibernate netbeans exception

我在 stackoverflow 上多次发现这个问题,但他们没有给我明确的答案。为了简单起见,只有两个表电影语言绑定(bind)了多对一的关系。一切按照Netbeans Hibernate DVD Store tutorial完成。现在,如何以首页(index.xhtml)语言显示。看起来非常简单。只需添加:

                  <h:column>
                    <f:facet name="header">
                        <h:outputText value="Language"/>
                    </f:facet>
                    <h:outputText value="#{item.languageByLanguageId.langName}"/>
                 </h:column>

(表中的语言名称已在langName上重命名) 但它仍然发出相同的 LazyInitializationException。我尝试获取 languageId,在本例中我成功了。这意味着 #{item.languageByLanguageId.langName} 给出了异常,但 #{item.languageByLanguageId.languageId} 没有。它很奇怪。那么,当我根据 languageId 使用显式获取(如果我可以获得它)时会发生什么。

所以我在FilmController.java中添加了获取语言的方法:

  public String getLanguageById(Integer langId) {
    String language = helper.getLangById(langId);
    return language;
  }

FilmHelper.java(最终版本)中:

  public Film getFilmById(int filmId) {

Film film = null;

try {
    session = HibernateUtil.getSessionFactory().getCurrentSession();
    org.hibernate.Transaction tx = session.beginTransaction();
    Query q = session.createQuery("select count(film.filmId) from Film as film where film.filmId = :filmId");
    q.setParameter("filmId", filmId);
    Number count = (Number) q.uniqueResult();
    if (count.intValue() > 0)
      film = (Film) session.load(Film.class, filmId);
    tx.commit();
} catch (Exception e) {
    e.printStackTrace();
}

return film;

}

是的,它有效,我可以获取语言名称来修改index.xhtml:

<h:outputText value="{filmController.getLanguageById(item.languageByLanguageId.languageId)}"/>

比我尝试修改 FilmActor.hbm.xml 以添加lazy="false"并在index.xhtml中使用原始简单解决方案("#{item.languageByLanguageId.langName}"):

<many-to-one name="languageByOriginalLanguageId" class="dvdrental.Language" lazy="false" fetch="select">
        <column name="original_language_id" />
    </many-to-one>

它再次正常工作。即使我设置了lazy="proxy"lazy="no proxy"。但我仍然不明白,如何使用这个默认属性lazy="true"。如果我尝试将整个文档保留在一个 session 中(不进行提交,这会导致 session 结束),则会出现另一个异常问题。看起来,lazy="true"在任何时候都无法达到正确的结果。

最佳答案

通过设置lazy=true属性,您可以允许hibernate延迟关联检索。因此,当您禁用lazy=false时,hibernate将在检索父实例后立即执行其获取方法。如果你设置fetch="join",你的问题就会得到解决。

Join fetching: Hibernate retrieves the associated instance or collection in the same SELECT, using an OUTER JOIN.

你的例子;

<many-to-one name="languageByOriginalLanguageId" class="dvdrental.Language" fetch="join">
        <column name="original_language_id" />
</many-to-one>

您可以将 fetch 和lazy 分别视为如何和何时。在您的示例中,lazy=false 解决了您的问题,但仍然完成了两个查询,因为您的 fetch 方法是 selectHibernate Fetching Strategies

更新

一旦对象被延迟初始化,你就只有实体的属性和延迟初始化关联(只有你拥有的id)。然后该对象被传递以供进一步使用(事务已提交),并且您想要使用惰性初始化关联之一(在您的情况语言中)并得到异常。发生这种情况是因为您正在访问惰性对象并且您的事务已经提交,因此 hibernate 想要执行第二个查询但没有成功(fetch =“select”)。这可以通过将读取关联的代码移至事务提交之前来解决。

当你的对象被分离并且当前 session 关闭时,你必须这样做

Hibernate.initialize(entity)

将您的分离实体分配给另一个 session 。

关于java - Hibernate 问题 : org. hibernate.LazyInitializationException:无法初始化代理 - 无 session ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/25962814/

相关文章:

java - JDialog关闭刷新JFrame问题

java - JPA同步问题,需要重新启动应用程序

java - Web 应用程序基于数据库数据返回 XML 文档的最佳方式(由 VXML 使用)?

java - netbeans 中的默认 glassfish 4.0 密码

java - 如何使用 AND 运算符使用两个或多个条件过滤 Netbeans Profiler 中的方法

java - 如何重用 StringTokenizer 对象

java - JBoss AS 5 中部署的 Java EE 的推荐分析方法

java - 使用 Java 开发可重用的模板项目

java - 将数据从一个数据库复制到另一个数据库时如何解决org.hibernate.StaleObjectStateException?

java - 努力在 Netbeans IDE 8.0.2 中安装/添加 JUnit 插件