使用 hibernate.enable_lazy_load_no_trans 解决 Hibernate Lazy-Init 问题 [英] 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
现在社区正在欢呼
<property name="hibernate.enable_lazy_load_no_trans" value="true"/>
说它解决了问题,但谨慎使用.
谨慎使用是什么意思?这个属性实际上有什么作用?
What they mean by use it with caution? What this property actually does?
请给我任何见解.提前致谢.
Please give me any insights. Thanks in advance.
推荐答案
这种方法的问题是你可以有 N+1 效果.
The problem with this approach is that you can have the N+1 effect.
假设您有以下实体:
public class Person{
@OneToMany // default to lazy
private List<Order> orderList;
}
如果您有一个返回 10K 人的报告,并且如果您在此报告中执行代码 person.getOrderList()
,则 JPA/Hibernate 将执行 10K 的查询.这就是 N+1 效应,您将无法控制将要执行的所有查询.
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.
现在想象一下,Order 如下所示:
Imagine now that Order is like below:
public class Order{
@OneToMany // default to lazy
private List<EmailSent> emailSentList;
}
想象一下,现在您对 person.getOrderList()
进行了迭代,并且对于每个 Order order
,您将执行一个 order.getEmailSentList()
代码>.你现在能看出问题吗?
Imagine now that you have a iteration with the person.getOrderList()
and for every Order order
you will do a order.getEmailSentList()
. Can you see the problem now?
对于 LazyInitializationException,您可以有一些解决方案:
For LazyInitializationException you can have some solutions:
- 使用 OpenInSessionInView 方法.您需要创建一个 WebFilter 来打开和关闭事务.问题在于 N+1 效应.
- 使用 hibernate.enable_lazy_load_no_trans 配置,这是一个休眠状态,如果需要,您将无法将您的项目移植到其他 JPA 提供程序.您也可以拥有 N+1 效果.
- 使用名为 PersistenceContext Extended 的 EJB 功能.有了这个,您将保持多个事务的上下文打开.问题是:可能发生 N+1 效应,使用大量服务器内存(实体将保持管理)
- 在查询中使用 FETCH.使用这种方法,您可以执行 JPQL/HQL,例如:
select p from Person p join fetch p.orderList
.使用此查询,您将从数据库加载您的列表,并且不会有 N+1 效果.问题是您需要为每种情况编写一个 JPQL.
- 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 these links:
这篇关于使用 hibernate.enable_lazy_load_no_trans 解决 Hibernate Lazy-Init 问题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!