gpt4 book ai didi

java - Hibernate 执行太多查询

转载 作者:搜寻专家 更新时间:2023-11-01 01:44:07 25 4
gpt4 key购买 nike

我认为我误解了 subselect 和 eager 的工作原理;我的目标是在遇到 N+1 问题时提高性能

编辑 我想知道只使用创建 SQL 查询方法并自己创建对象是否会更快,尽管我希望 hibernate 能与性能相提并论。在下面的示例中,我可以在单个查询中提取所需的所有数据,那么到底为什么 hibernate 要为每个数据执行单独的查询?

我创建了以下测试用例来突出我的问题,请原谅这个模型的粗鲁......

@Entity
@Table(name = "Area")
public class Area implements Serializable
{
@Id
@GeneratedValue(generator = "areaId" )
@GenericGenerator(name = "areaId", strategy = "uuid2")
public String areaId;

@OneToMany(mappedBy = "area", fetch=FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
public Set<EmployeeArea> employeeAreas = new HashSet<EmployeeArea>();
}

@Entity
@Table(name = "Employee")
public class Employee implements Serializable
{
@Id
@GeneratedValue(generator = "employeeId" )
@GenericGenerator(name = "employeeId", strategy = "uuid2")
public String employeeId;

@OneToMany(mappedBy = "employee", fetch=FetchType.EAGER)
@Fetch(FetchMode.SUBSELECT)
public Set<EmployeeArea> employeeAreas = new HashSet<EmployeeArea>();
}

@Entity
@Table(name = "EmployeeArea")
public class EmployeeArea implements Serializable
{
@Id
@GeneratedValue(generator = "employeeAreaId" )
@GenericGenerator(name = "employeeAreaId", strategy = "uuid2")
public String employeeAreaId;

@Id
@ManyToOne
public Employee employee;

@Id
@ManyToOne
public Area area;
}

然后我填充了一些示例测试数据:-

Employee employee = new Employee();
Area area = new Area();

EmployeeArea employeeArea = new EmployeeArea();
employeeArea.area = area;
employeeArea.employee = employee;

session.save(employee);
session.save(area);
session.save(employeeArea);

这可以运行几次以提供一些数据。

然后我执行以下操作:-

session.createQuery("FROM Employee e INNER JOIN e.employeeAreas ea INNER JOIN ea.area").list();

我进行 JOIN 的原因是我可以执行专业搜索。我正在查看标准,但它似乎不允许我用 WHERE 做我能做的一切

我希望它最多执行 3 个查询和 2 个子查询。

  1. SELECT * FROM Employee INNER JOIN EmployeeArea ON 条件 INNER JOIN Area ON 条件
  2. SELECT * FROM Employee WHERE employeeId IN(子查询 1)
  3. SELECT * FROM Area WHERE areaId IN(子查询 2)

事实上,对于上述测试数据的 6 个输入,我似乎为一名员工获得了 6 个选择,为一个区域获得了 6 个选择,这看起来像我假设的查询“1”。然后是两个看起来完全错误的更大的查询:-

select
employeear0_.employee_employeeId as employee2_3_2_,
employeear0_.employeeAreaId as employee1_4_2_,
employeear0_.employee_employeeId as employee2_4_2_,
employeear0_.area_areaId as area3_4_2_,
employeear0_.employeeAreaId as employee1_4_1_,
employeear0_.employee_employeeId as employee2_4_1_,
employeear0_.area_areaId as area3_4_1_,
area1_.areaId as areaId1_0_0_
from
EmployeeArea employeear0_
inner join
Area area1_
on employeear0_.area_areaId=area1_.areaId
where
employeear0_.employee_employeeId in (
select
employee1_.employeeId
from
EmployeeArea employeear0_
inner join
Employee employee1_
on employeear0_.employee_employeeId=employee1_.employeeId
where
employeear0_.area_areaId in (
select
area2_.areaId
from
Employee employee0_
inner join
EmployeeArea employeear1_
on employee0_.employeeId=employeear1_.employee_employeeId
inner join
Area area2_
on employeear1_.area_areaId=area2_.areaId
)
)

然后是一个非常相似的区域。

我的目标是能够使用返回列表中的每个员工对象来识别工作区域。每个实体中会有更多字段,但此测试用例已得到简化。

最佳答案

我解决了这个问题;这是我的连接表的问题。请参阅以下内容:-

@Id
@ManyToOne
public Employee employee;

@Id
@ManyToOne
public Area area;

我使用了 @Id,这导致了抛出的 StackOverflowError 异常。使用以下查询,通过对 Employee 的 EAGER 和 @Fetch JOIN 的 OneToMany 提取以及对 Area 的 LAZY 和 @Fetch SELECT 的 OneToMany 提取,然后我可以执行以下查询:-

List<Employee> employees = session.createQuery("FROM Employee e INNER JOIN FETCH e.employeeAreas ea INNER JOIN FETCH ea.area").list();

同时能够在其中一个连接表列上使用 WHERE。

关于java - Hibernate 执行太多查询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17094794/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com