我有下一个班级结构
@Entity
@Table(name = "Company")
public class Company {
@Id
@GeneratedValue
private Long id;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "CompanyId")
@Fetch(FetchMode.SUBSELECT)
private Set<Departement> departements;
}
@Entity
@Table(name = "Departement")
public class Departement {
@Id
@GeneratedValue
private Long id;
@OneToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "DepartementId")
@Fetch(FetchMode.SUBSELECT)
private Set<Employee> employees;
}
@Entity
@Table(name = "Employee")
public class Employee {
@Id
@GeneratedValue
private Long id;
// other fields and methods
}
在应用程序启动时,我需要使用已初始化的内部集合来获取所有公司。我的数据库足够大(公司表中有1,5 M行)。我需要解决n + 1选择问题以加速数据检索。带有提取连接的解决方案在我的情况下不起作用,因为生成的sql查询返回了大量的数据集,即使我像这样使用滚动
Query query = session.createQuery(query);
query.setReadOnly(true);
// MIN_VALUE gives hint to JDBC driver to stream results
query.setFetchSize(Integer.MIN_VALUE);
ScrollableResults results = query.scroll(ScrollMode.FORWARD_ONLY);
它仍然消耗我的所有RAM,因为我无法刷新会话或驱逐检索到的实体。
另一种方法是使用子选择,但是当我这样做时
@SuppressWarnings("unchecked")
List<Company> companies = session.createQuery("from Company").list();
for (Company c : companies) {
for (Departement d : c.getDepartements()) {
d.getEmployees();
}
}
hibernate只生成2个查询:一个用于公司表
select ... from Company company
和另一个部门表
select ... from Departement departemen0_
where departemen0_.CompanyId in (select company0_.id from Company company0_)
我仍然需要分别从Departement类初始化员工集合。
有没有办法用子选择检索所有3个表?或者可能有另一种方法来检索给定结构的大量数据?
答案 0 :(得分:0)
您的代码仅生成两个查询(针对公司和部门),因为您的员工查询代码(第三个也是所需的)没有被延迟获取。因此,只需更改:
d.getEmployees();
收件人:
d.getEmployees().size();
如果您要处理的数据量如此,SUBSELECT
似乎是best strategy的理想之选:
- JOIN:避免了主要的N + 1查询问题,但它可以检索重复的数据。
- SUBSELECT:也避免N + 1并且不重复数据,但是它将所有关联类型的实体加载到内存中。