Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans

I have been suffering from infamous hibernate exception

org.hibernate.LazyInitializationException: could not initialize proxy - no Session

Now the community is cheering over

<property name="hibernate.enable_lazy_load_no_trans" value="true"/>

saying it solves the problem but USE IT WITH CAUTION.

What they mean by use it with caution? What this property actually does?

Please give me any insights. Thanks in advance.

java hibernate jpa persistence lazy-initialization


shareimprove this question

asked Aug 18 ‘14 at 12:01

Sachin Verma
964837

 

1  

this might help you – ankur-singhal Aug 18 ‘14 at 12:48
    

Looks like the link has changed to harezmi.com.tr/… – Steve Chambers Jul 1 at 10:15

add a comment

3 Answers

activeoldestvotes


up vote15down vote

The problem with this approach is that you can have the N+1 effect.

Imagine that you have the following entity:

public class Person{
    @OneToMany // default to lazy
    private List<Order> orderList;
}

If you have a report that returns 10K of persons, and if in this report you execute the code person.getOrderList() the JPA/Hibernate will execute 10K of queries. This is the N+1 effect, you will have no control about all the queries that will be executed.

Imagine now that Order is like below:

public class Order{
    @OneToMany // default to lazy
    private List<EmailSent> emailSentList;
}

Imagine now that you have a iteration with the person.getOrderList() and for every Order orderyou will do a order.getEmailSentList(). Can you see the problem now?

For LazyInitializationException you can have some solutions:

  • Use the OpenInSessionInView approach. You will need to create a WebFilter that will open and close the transaction. The problem with is the N+1 effect.
  • Use the hibernate.enable_lazy_load_no_trans configuration, that is a hibernate and you will not be able to port your project to other JPA provider if needed. You also can have the N+1 effect.
  • Use the EJB feature named PersistenceContext Extended. With this you will keep the context opened of several transactions. The problems are: N+1 effect can happen, use a lot of server memory (entities will stay managed)
  • Use the FETCH in the query. With this approach you could do a JPQL/HQL like: select p from Person p join fetch p.orderList. With this query you will have your list loaded from the database and will not have the N+1 effect. The problem is that you will need to write a JPQL for each case.

If you still have any problem, check this link: http://uaihebert.com/four-solutions-to-the-lazyinitializationexception


shareimprove this answer

answered Aug 18 ‘14 at 16:32

uaiHebert
1,345215

 

    

OpenSessionInView will never have this "N+1 effect", that would‘nt make any sense. Only ONE session will be opened and every entity-lookup within that will be handled normally - most likely via JOINs, depending on your fields. You have obviously not understood how the open-session-in-view method works. The one and only problem with it is : in bad situations (and with bad coding) your user may not get any information if your transaction actually got rolled back or even failed, dending on your transaction-configuration. – specializt Oct 14 ‘14 at 11:20 
    

N+1 is not about several sessions, but is about several trips do the database. – uaiHebert Oct 14 ‘14 at 14:36
    

in this case these are the same thing - during a view-created session all of your entity attributes may or may not be fetched with a single "trip" - depending on your ORM-implementation and/or fetch configuration. – specializt Oct 15 ‘14 at 12:12 
    

I am not sure if you understood what I told up there. With open session in view you will have the N+1 effect, you will keep the transaction opened and for each get of a non fetched entity a new trip to the database will be done. I said about n+1 and fetch in a jpql, what is your point? – uaiHebert Oct 15 ‘14 at 18:39
    

ohgod ... that engrish is hard to decrypt, anyway : yes, you now discovered the primary aspect of lazy initialization. I recommend going deeper into the topic; such as the difference to eager-fetch, cardinalities and especially the fact that your "problem" is omnipresent and a JOIN FETCH will simply remove the DBMS-driver overhead for a few additional "trips" but also decrease the performance in large data-sets. JOINs may work for small data-sets exclusively. Hybrid approaches may also yield acceptable results. – specializt Oct 15 ‘14 at 19:39

show 2 more comments

Did you find this question interesting? Try our newsletter

Sign up for our newsletter and get our top new questions delivered to your inbox (see an example).


up vote4down vote

This goes against how we can take advantage of Hibernate‘s enforcement of repeatable read semantics with the Session concept. When an object is first loaded and if the object is referenced again within the life of the session, then the same object is returned IRRESPECTIVE of whether this object has changed in the DB. This is the repeatable read semantics provided automatically by hibernate.

With this setting, you have no session providing this guarantee, so if you now access this data you will be getting the latest version of the data.

This might be fine. But consider the scenario where this object is held in some place for a long time and the data has changed considerably, so that the lazily fetched data is much different that the data already loaded when the session was alive. This is what you need to be concerned about.

To put it simple you can safely use this setting if your program is not affected by: How stale the data that was already fetched when in session to the data that will be fetched lazily out of session

But if this (your program is exposed to timing issues, when it might work fine one time and fail another time) is a concern, then fetch all the necessary data while in session.


shareimprove this answer

answered May 25 at 19:25

ddalton
86827

 
add a comment

up vote1down vote

Probably because there are better solutions, like @Transactional, where opening and closing sessions follows a very common pattern of "open a session then wrap everything in a try-catch-finally; catch rolls back and finally closes the session." This annotation is typically at the request-level for web apps and services.

Or if you need more granular control you can open sessions manually using a SessionFactory.

And as others have mentioned, lazy-loading is something you need to be aware of. It‘s not a silver bullet but it can be very helpful. Generally, if your apps are designed to have many small requests then its ok.

Eager loading can also be very bad. For example, when your object model has lots of many-to-many relationships but your requests don‘t use data more than one level deep.

Or you can just forget the whole thing for now. Use lazy loading until it becomes an issue. And if it does, you would have been better of with Mybatis anyway.


shareimprove this answer

answered May 21 at 2:00

James Watkins
1,0491515

http://stackoverflow.com/questions/25362831/solve-hibernate-lazy-init-issue-with-hibernate-enable-lazy-load-no-trans

时间: 2024-10-15 07:07:42

Solve Hibernate Lazy-Init issue with hibernate.enable_lazy_load_no_trans的相关文章

Hibernate Lazy属性

1 延迟加载策略 Hibernate 的延迟加载(lazy load)是一个被广泛使用的技术.这种延迟加载保证了应用只有在需要时才去数据库中抓取相应的记录.通过延迟加载技术可以避免过多.过早地加载数据表里的数据,从而降低应用的内存开销.Hibernate 的延迟加载本质上就是代理模式的应用,当程序通过 Hibernate 装载一个实体时,默认情况下,Hibernate 并不会立即抓取它的集合属性.关联实体所以对应的记录,而是通过生成一个代理来表示这些集合属性.关联实体,这就是代理模式应用带来的优

hibernate lazy和fetch属性介绍

lazy延迟加载 lazy(延迟加载)策略可用于<class>标签,<property>标签,集合(<set>/<list>)标签以及<one-to-one>/<many-to-one>标签上 <class> class标签中的lazy可选属性为true/false,默认为ture,代表默认使用延迟加载策略 1 public static void main(String[] args) { 2 Session sessi

hibernate篇章六--demo(Hibernate之第1解之-hibernate_demo_1)

准备工作做好了,开始Hibernate: 1:建立包:package:dao.model.service.util包: 2:开始model实体类Student:id,sname生成getter/setter: Java代码 1 package model; 2 3 public class Student { 4 private int id; 5 private String name; 6 7 public int getId() { 8 return id; 9 } 10 private

【Hibernate那点事儿】—— Hibernate应该了解的知识

前言: 最近由于有点时间,就像深入的学习一下Hibernate.之前只是简单的使用,并没领会它的妙处.这里就趁着分享的机会,好好整理一下. 这篇主要讲到了下面几个部分: Hibernate框架 Hibernate发展背景 Hibernate使用介绍 Hibernate Tools安装 Hibernate那些必要的包 首先说一下,这个Hibernate是做什么的.Hibernate官网上面罗列了它的基本框架 我们最常用的应该就是Hibernate ORM了.下面简单的说下几个框架的作用: Hibe

Hibernate学习---第二节:hibernate 增、删、改、查

1.增,向数据库中写入数据,代码如下: /** * 数据保存 * 1.save() * 2.persist() */ @Test private void testSave(){ Configuration config = new Configuration().configure(); /** * 获取连接工程场 * 通常对应一个数据库,通常一个应用程序只有一个,再启动的时候创建 * 线程安全 */ /** * buildSessionFactory() 属于 hibernate3 中的方法

web工程单独使用hibernate(用于测试以及hibernate入门)

1 首先下载hibernate包地址:http://hibernate.org/orm/ 2 新建web工程,添加hibernate的lib参考包(将第一步解压的文件里的lib文件夹下required文件夹下的jar包复制到web工程的webroot的web-inf的lib下) 3 文件结构如图 4 Test类用作测试效果:代码: package com.sinosoft; import org.hibernate.Session; import org.hibernate.SessionFac

hibernate 大对象类型的hibernate映射

基本知识: 在 Java 中, java.lang.String 可用于表示长字符串(长度超过 255), 字节数组 byte[] 可用于存放图片或文件的二进制数据. 此外, 在 JDBC API 中还提供了 java.sql.Clob 和 java.sql.Blob 类型, 它们分别和标准 SQL 中的 CLOB 和 BLOB 类型对应. CLOB 表示字符串大对象(Character Large Object), BLOB表示二进制对象(Binary Large Object) Mysql

Hibernate笔记①--myeclipse制动配置hibernate

Hibernate 是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库. Hibernate可以应用在任何使用JDBC的场合,既可以在Java的客户端程序使用,也可以在Servlet/JSP的Web应用中使用,最具革命 意义的是,Hibernate可以在应用EJB的J2EE架构中取代CMP,完成数据持久化的重任. Hibernate笔记①--myeclipse制动配置hibernate

Hibernate框架 主配置文件(Hibernate.cfg.xml) 映射配置 说明

Hibernate.cfg.xml 主配置文件中主要配置:数据库连接信息.其他参数.映射信息! 常用配置查看源码: hibernate-distribution-3.6.0.Final\project\etc\hibernate.properties   <!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://www.hiber

攻城狮在路上(壹) Hibernate(七)--- 通过Hibernate操纵对象(下)

一.与触发器协同工作: 当Hibernate与数据库的触发器协同工作时,会出现以下两类问题: 1.触发器使Session缓存中的数据和数据库中的不一致: 出现此问题的原因是触发器运行在数据库内,它执行的操作对Session是透明的. 解决方案:在执行完包含有触发器的操作之后,立刻调用Session的flush()和refresh()方法,迫使Session的缓存与数据库同步. 2.Session的update()方法盲目的激发触发器: 这种情况主要发生在Session调用update()或sav