Java JPA 一对多关系查询
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22221006/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
JPA one to many relationship query
提问by user3157090
Implemented one to many relationship and it is working fine.
实现了一对多关系,并且运行良好。
My issue is when i run the below query, if the table has 100 employee rows, and each employee has 2 departments. The database query is called 101 times, because for each employee it is calling department query, it is taking very long to complete calling all hundred rows, can any one suggest any alternative solution?
我的问题是当我运行以下查询时,如果表有 100 个员工行,并且每个员工有 2 个部门。数据库查询被调用 101 次,因为对于每个员工调用部门查询,完成调用所有一百行需要很长时间,有人可以提出任何替代解决方案吗?
Please see the details below
请看下面的详细信息
Queries it is calling:
它正在调用的查询:
First query is : SELECT * FROM Employee e
Next 100 queries : SELECT * FROM DEPARTMENT d WHERE d.EmployeeId=?
JPA Database call :
JPA 数据库调用:
javax.persistence.Query query = em.createNamedQuery("SELECT * FROM Employee e", Employee.class);
return query.getResultList();
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.Id;
import javax.persistence.NamedNativeQueries;
import javax.persistence.NamedNativeQuery;
import javax.persistence.OneToMany;
import javax.persistence.Table;
@Entity
@Table(name = "EMPLOYEE")
public class Employee implements Serializable
{
@Id
@Column(name = "EmployeeId")
String employeeId;
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Department> departments;
public List<Department> getDepartments() {
return departments;
}
public void setDepartments(List<Department> departments) {
this.departments = departments;
}
public String getEmployeeId() {
return employeeId;
}
public void setEmployeeId(String employeeId) {
this.employeeId = employeeId;
}
}
@Entity
@Table(name = "DEPARTMENT")
public class Department implements Serializable
{
private static final long serialVersionUID = 1L;
@Id
@Column(name = "DepartmentID")
String departmentId;
@ManyToOne(fetch = FetchType.EAGER)
@JoinColumn(name = "EmployeeId", insertable = false, updatable = false)
private Employee employee;
}
The output xml:
输出xml:
<Employees>
<Employee>
<name>Rob</name>
<Departments>
<Departmnet><id>1</id></Departmnet>
<Departmnet><id>2</id></Departmnet>
</Departments>
</Employee>
<Employee>
<name>Sam</name>
<Departments>
<Departmnet><id>1</id></Departmnet>
<Departmnet><id>2</id></Departmnet>
</Departments>
</Employee>
</Employees>
采纳答案by Cascader
This is a typical N+1 selects issue. I usually solve this with JOIN FETCH
queries as described hereand here
回答by Kevin Bowersox
You could switch the fetchtype to lazy, which will cause the departments only to be queried when necessary.
您可以将 fetchtype 切换为惰性,这将导致仅在必要时查询部门。
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
private List<Department> departments;
回答by zawhtut
Change FetchType.EAGER
to FetchType.LAZY
. Load the departments only when you need them which is looping the employee.getDepartmentList() for example
更改FetchType.EAGER
为FetchType.LAZY
。仅在需要时才加载部门,例如循环 employee.getDepartmentList()
for(Department dept:employeeGetDepartmentList()){
dept.getId();
}
before using departments
在使用部门之前
回答by ikettu
Classic N+1 problem. You can reduce number of queries with Batch Fetching which just combines many lazy sql clauses to single one.
经典的 N+1 问题。您可以使用 Batch Fetching 减少查询数量,它只是将许多惰性 sql 子句组合为一个。
For Example:
例如:
@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
@BatchSize(size=10)
private List<Department> departments;