如何解决使用JPA和Hibernate时的LazyInitializationException

2022-08-31 20:08:10

我正在为想要使用惰性初始化的客户做一个项目。当使用默认的延迟加载模式映射类时,它们总是得到“延迟初始化异常”。

@JoinTable(name = "join_profilo_funzionalita", joinColumns = {@JoinColumn(name =    "profilo_id", referencedColumnName = "profilo_id")}, inverseJoinColumns = {@JoinColumn(name = "funzionalita_id", referencedColumnName = "funzionalita_id")})
//@ManyToMany(fetch=FetchType.EAGER) - no exceptions if uncommented
@ManyToMany 
private Collection<Funzionalita> funzionalitaIdCollection;

是否有使用 JPA 类的标准模式来避免此错误?

欢迎提供摘要,非常感谢您抽出宝贵时间。


答案 1

Hibernate 4.1.6终于解决了这个问题:https://hibernate.atlassian.net/browse/HHH-7457

您需要将休眠属性设置为 hibernate.enable_lazy_load_no_trans=true

以下是在春季操作的方法:

<bean id="entityManagerFactory"
      class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
    <property name="dataSource" ref="myDataSource"/>
    <property name="packagesToScan" value="com.mycompany.somepackage"/>
    <property name="jpaVendorAdapter" ref="hibernateVendorAdapter"/>
    <property name="jpaDialect" ref="jpaDialect"/>
    <property name="jpaProperties">
        <props>
            <prop key="hibernate.enable_lazy_load_no_trans">true</prop>
        </props>
    </property>
</bean>

瞧;现在,您不必担心 LazyInitializationException,同时在休眠会话之外导航域模型(“JPA-speak”中的持久性上下文)


答案 2

有许多方法可以预取属性,因此它们在会话关闭后就在那里:

  1. 调用适当的 getter。在将字段提取到 Bean 中后,它在会话关闭后就在那里。
  2. 您可以在 EJBQL 查询 中初始化字段,查找关键字。JOIN FETCH
  3. 启用AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS如果您使用的是支持它的休眠版本。

当您尝试以下解决方案时,可能会出现几个问题:

  1. getters 的调用可能会被 JIT 编译器优化掉(有时这需要一段时间)。
  2. 您尝试的实体可能通过涉及列表的多个“许多”关系进行链接。在这种情况下,生成的查询将返回不明确的结果,并且 Hibernate 将拒绝在单个查询中获取您的数据。JOIN FETCH
  3. 已经有一个与AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS相关的有趣错误。而且会有更多的,因为正如冬眠的人所说:注意:这可能发生在交易之外,不安全。请谨慎使用。你大部分时间都是靠自己。

最好的方法是尝试第一次。如果这不起作用,请尝试 getter 方法。如果 JIT 编译器在运行时搞砸了,请将结果分配给 .JOIN FETCHpublic static volatile Object

或者停止使用休眠...


推荐