这种方法的问题在于你可以产生N + 1效果。
假设你具有以下实体:
public class Person{ @oneToMany // default to lazy private List<Order> orderList;}
如果你有一个返回1万个人的报告,并且在此报告中执行了代码,
person.getOrderList()那么J
PA / Hibernate将执行10K查询。这是N + 1效果,你将无法控制将要执行的所有查询。
现在想象一下,订单如下所示:
public class Order{ @oneToMany // default to lazy private List<EmailSent> emailSentList;}
想象一下,现在你使用进行了一次迭代,
person.getOrderList()并且每
Order order做一次
order.getEmailSentList()。现在可以看到问题了吗?
对于LazyInitializationException,你可以有一些解决方案:
- 使用OpenInSessionInView方法。你将需要创建一个WebFilter来打开和关闭事务。问题在于N + 1效应。
- 使用hibernate.enable_lazy_load_no_trans配置,即hibernate状态,如果需要,你将无法将项目移植到其他JPA提供程序。你还可以具有N + 1效果。
- 使用名为PersistenceContext Extended的EJB功能。这样,你将使多个事务的上下文保持打开状态。问题是:可能发生N + 1效应,使用大量服务器内存(实体将保持托管状态)
- 在查询中使用FETCH。使用这种方法,你可以执行JPQL / HQL,如:
select p from Person p join fetch p.orderList
。通过此查询,你将从数据库中加载列表,并且不会产生N + 1效果。问题是你将需要为每种情况编写一个JPQL。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)