这种方法的问题在于,你可以产生N+1效应。
假设您有以下实体:
public class Person{
@OneToMany // default to lazy
private List<Order> orderList;
}
如果您有一个返回 10K 人员的报告,并且在此报告中执行代码,则 JPA/Hibernate 将执行 10K 个查询。这是N + 1效应,您将无法控制将要执行的所有查询。person.getOrderList()
现在想象一下,订单如下:
public class Order{
@OneToMany // default to lazy
private List<EmailSent> emailSentList;
}
想象一下,现在你有一个迭代与 和 对于每个你将做一个 .你现在能看到问题吗?person.getOrderList()
Order order
order.getEmailSentList()
对于 LazyInitializationException,你可以有一些解决方案:
- 使用 OpenInSessionInView 方法。您将需要创建一个将打开和关闭事务的 Web 筛选器。问题是N+1效应。
- 使用hibernate.enable_lazy_load_no_trans配置,即休眠,如果需要,您将无法将项目移植到其他 JPA 提供程序。您还可以具有N + 1效果。
- 使用名为 PersistenceContext Extended 的 EJB 功能部件。这样,您就可以保持多个事务的上下文打开。问题是:N + 1效应可能发生,使用大量服务器内存(实体将保持管理)
- 在查询中使用 FETCH。使用这种方法,你可以做一个JPQL /HQL,比如:。使用此查询,您将从数据库加载列表,并且不会产生 N+1 效果。问题是你需要为每个情况编写一个JPQL。
select p from Person p join fetch p.orderList
如果仍有任何问题,请检查以下链接: