当前位置:  开发笔记 > 编程语言 > 正文

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

如何解决《如何在使用JPA和Hibernate时解决LazyInitializationException》经验,为你挑选了6个好方法。

我正在为一个想要使用延迟初始化的客户开发一个项目.当使用默认延迟加载模式映射类时,它们总是会出现"延迟初始化异常".

@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 funzionalitaIdCollection;

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

欢迎使用片段,非常感谢您的时间.



1> andreak..:

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

您需要设置hibernate属性hibernate.enable_lazy_load_no_trans = true

以下是在Spring中如何做到这一点:


    
    
    
    
    
        
            true
        
    

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


不要使用这个功能.它坏了,你会丢失你的数据.https://hibernate.atlassian.net/browse/HHH-7971
在Hibernate版本4.3.5中修复了该错误.从Hibernate版本开始,此功能使用是安全的.
您能否在答案中添加此属性的确切功能?该实现可能会对数据一致性或性能产生严重影响。可能两者都有。
此选项将延迟关联加载到事务外部,这意味着数据可能与父实体的数据不一致。但这并不比使用Spring的OpenEntityManagerInViewFilter差,后者还可以在事务外加载内容。我正在使用基于字段的映射,还没有体验过JIT弄乱生成的代理。

2> jb...:

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

    调用适当的getter.在将字段提取到bean之后,会话关闭后就会存在.

    您可以在EJBQL查询中初始化字段,查找JOIN FETCH关键字.

    如果您使用的是支持它的Hibernate版本,请启用AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS.

尝试这些解决方案时可能会出现几个问题:

    JIT编译器可能会优化getter的调用(有时需要一段时间).

    您尝试的实体JOIN FETCH可能通过涉及List的多个"多"关系进行链接.在这种情况下,生成的查询返回不明确的结果,Hibernate将拒绝在单个查询中获取您的数据.

    已有一个与AvailableSettings.ENABLE_LAZY_LOAD_NO_TRANS相关的有趣错误.还有更多因为hibernate的人说:注意:这可能发生在交易之外并且不安全.谨慎使用.你主要是靠自己.

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

或者停止使用Hibernate ...


"或者停止使用Hibernate ......"......阿门.

3> 小智..:

请注意,您不应该使用hibernate.enable_lazy_load_no_transpre Hibernate 4.1.7,因为它会泄漏连接.请参阅https://hibernate.onjira.com/browse/HHH-7524



4> Daniel Alexi..:

LazyInitializationException意味着您在hibernate会话关闭后或者在从会话中分离对象之后调用该集合.

您需要将对象重新附加到休眠会话,更改调用集合的位置,或将会话关闭的边界移动到更高层.


这很好但是怎么样?
确切地说,我们得到了什么部分; 怎么回事!

5> cliff.meyers..:

OpenSessionInView是一种处理这个问题的模式.一些信息在这里:

http://www.hibernate.org/43.html

在实现此模式并理解其含义时,您需要谨慎.每次在视图中导航延迟关联时,它都会触发另一个SQL查询来加载数据.如果您的用例是这些SQL查询的数量和大小很小,那么这可能无关紧要.确保至少调整日志记录设置,以便查看Hibernate在后台"神奇地"执行哪种查询以便加载数据.

还要考虑您正在编写的应用程序类型.如果您不处理远程处理(没有Web服务,没有基于AJAX的Web客户端),那么OSIV可能会非常好用.但是,如果远程处理序列化程序开始遍历整个对象图,则可能会触发大量的SQL查询并使您的数据库和应用服务器瘫痪.



6> Vlad Mihalce..:

解决LazyInitializationException的最佳方法是在实体查询中使用JOIN FETCH指令.

EAGER加载对性能不利.此外,还有反模式,如:

在视图中打开会话

hibernate.enable_lazy_load_no_trans

您永远不应该使用它,因为它们要求为UI呈现打开数据库连接(在视图中打开会话),或者在初始持久性上下文(hibernate.enable_lazy_load_no_trans)之外获取的每个惰性关联都需要数据库连接.

有时,您甚至不需要实体,DTO投影甚至更好.只有在需要修改实体时才应获取实体.对于只读事务,DTO预测更好.

推荐阅读
yzh148448
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有