サブセレクトとイーガーがどのように機能するかを誤解していると思います。私の目標は、N+1 問題に遭遇したときのパフォーマンスを改善することです
編集休止状態がパフォーマンスと同等であることを望んでいましたが、 create SQL query メソッドを使用して自分でオブジェクトを作成する方が速いかどうか疑問に思っています。以下の例では、必要なすべてのデータを 1 つのクエリで取得できるのに、なぜ 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 つのサブクエリを実行すると予想されます。
- SELECT * FROM Employee INNER JOIN EmployeeArea ON条件 INNER JOIN Area ON条件
- SELECT * FROM Employee WHERE employeeId IN (サブクエリ 1)
- SELECT * FROM Area WHERE areaId IN (サブクエリ 2)
実際、前述のテスト データの 6 つの入力に対して、従業員に対して 6 つの選択、エリアに対して 6 つの選択を取得しているように見えます。そして、明らかに間違っているように見える 2 つの大きなクエリ: -
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 ) )
次に、面積について非常によく似たものです。
私の目標は、返されたリスト内の各従業員オブジェクトを使用して、働いていた分野を特定できるようにすることです。各エンティティにはより多くのフィールドがありますが、このテスト ケースは単純化されています。