【问题标题】:Using OpenSessionInViewInterceptor to avoid LazyInitializationException使用 OpenSessionInViewInterceptor 避免 LazyInitializationException
【发布时间】:2011-04-04 08:03:57
【问题描述】:

首先我需要承认我是 EJB、JPA 和 Spring 的新手,所以我认为正确的许多事情都可能是错误的。

我正在构建一个 EJB 应用程序,其中有一个无状态会话 bean 用于检索许多 JPA (Hibernate) 实体。这个问题,我认为是一个普遍存在的问题,是当无状态返回任何实例时,我无法遍历这些实体的关系。我得到了可怕的 LazyInitializationException。在许多情况下,我发现使用 Eager fetching 可以避免异常,但这感觉更像是一种解决方法,而不是真正的修复。经过大量的谷歌搜索,我发现(因为我使用的是 spring)可能最侵入性的方法是使用 OpenSessionInViewInterceptor。

阅读this看起来好用,但是我无法映射文章中提到的文件。一种可能的解释是我使用的是 Spring 3,因此文件的名称可能已更改。我确实有一个 spring3app-servlet.xml 在其中声明了 bean。我还有一个设置过滤器的 web.xml(我相信这个文件在 spring 2.0 中使用过,但它仍然适用于 3.0)。

进一步的搜索让我意识到文件名不是我唯一关心的问题,因为我没有任何 SessionFactory bean,我相信这是它工作所必需的。这导致我搜索有关 SessionFactory bean 的信息。

该搜索让我意识到我可能需要 .hbm.xml 文件。我不确定这些文件是否真的需要,或者它们是否是旧版 hibernate-spring 版本所必需的。

tl;dr:我想要一个 OpenSessionInViewInterceptor。我需要一个 SessionFactory Bean 吗?我需要 .hbm.xml 文件吗?我在哪里可以找到所有设置信息?

编辑:

也许解决方案是使用 OpenSessionInViewFilter。我正在尝试使用它,但它仍然失败并出现同样的异常。我正在阅读 this 以寻求修复。

【问题讨论】:

    标签: hibernate spring jpa ejb lazy-loading


    【解决方案1】:

    首先,如果您想要一个全面的 JPA 解决方案,您应该使用 OpenEntityManagerInViewFilter。它的功能类似于 OpenSessionInViewInterceptor,但适用于 JPA

    对于会话 bean,您总是会收到 LazyInitializationException,因为对象是在不同的会话中加载的。惰性字段只能在当前的 http 请求中访问。如果您在另一个 http 请求中访问该字段,您将得到一个 LazyInitializationException。

    (顺便说一句,hibernate 将 http 请求定义为“Session”。但是 Spring 会话涵盖了多个 http 请求。是的,这很令人困惑)。

    避免 LazyInitializationException 的方法是:

    1. 重新加载会话 bean。例如:

      MyObject objectFromDb = objectDAO.find(objectFromSession.getId());

    2. 或在会话 bean 中设置字段时初始化该字段:

      Hibernate.initialize(field);

    (不要忘记递归所有子字段)


    好的,因为这是同一个会话,所以您确实需要一个 OpenEntityManagerInViewFilter/OpenSessionInViewInterceptor,它将为每个 Http 请求创建一个 Hibernate 会话。所以在你的 web.xml 中添加一个条目:

        <filter>
            <filter-name>JpaFilter</filter-name>
            <filter-class>org.springframework.orm.jpa.support.OpenEntityManagerInViewFilter</filter-class>
        </filter>
        <filter-mapping>
            <filter-name>JpaFilter</filter-name>
            <url-pattern>*.jsp</url-pattern>
        </filter-mapping>
    

    OpenEntityManagerInViewFilter 类似。还要确保将“entityManagerFactory”bean 注入到过滤器中。

    【讨论】:

    • 我没有涵盖多个请求,它们都在同一个请求中。这就是为什么我认为 spring-managed-session 应该可以解决我的问题。
    • @Doppelganger 我已经更新了我的答案以反映 OpenEntityManagerInViewFilter 的使用
    • 我正在尝试使过滤器工作,但我遇到了很多问题。我添加了 spring-orm 的 maven 依赖项,现在我遇到了这个问题: 10:55:06,457 错误 [[/system]] 异常启动过滤器 openEntityManagerInViewFilter java.lang.NoClassDefFoundError: org/springframework/dao/DataAccessResourceFailureException 我会如果我能让它工作,请回复你。另外,将电动势注入过滤器是什么意思?
    • @Doppelganger OpenEntityManagerInViewFilter 需要一个 emf 才能正常工作。我不知道你的注入是如何完成的(按名称命名?明确的?)只要确保过滤器注入了一个 emf(它需要一个才能正常工作!)
    • @Thierry-Dimitri Roy 我用@EJB注释注入它,在我用作DAO的ssb上,我不知道如何使用/如何处理过滤器,除了在 web.xml 中添加你给我的 XML
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-09-19
    • 2011-09-16
    • 1970-01-01
    • 1970-01-01
    • 2019-08-11
    • 1970-01-01
    • 2011-03-31
    相关资源
    最近更新 更多