2014-03-06 208 views
5

實現一對多關係,工作正常。JPA一對多關係查詢

我的問題是當我運行下面的查詢,如果該表有100個員工行,並且每個員工有2個部門。數據庫查詢被稱爲101次,因爲對於每個員工來說都是調用部門查詢,完成調用所有的100行花費很長時間,任何人都可以提出任何替代解決方案嗎?

請參考下面

查詢詳情它呼籲:

First query is : SELECT * FROM Employee e 

    Next 100 queries : SELECT * FROM DEPARTMENT d WHERE d.EmployeeId=? 

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; 
    } 

輸出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> 
+0

你爲什麼不使用聯接 –

+1

@PhilippSander:你可能指的是抓取連接?畢竟這是JPA,持久性提供者會爲你加入。 – Gimby

回答

4

這是一個典型的N+1 selects issue前循環的employee.getDepartmentList()例如

for(Department dept:employeeGetDepartmentList()){ 
dept.getId(); 
} 

。我通常用JOIN FETCH來解決這個問題described herehere

1

你可以切換fetc htype轉爲懶惰,這將導致部門只在必要時被查詢。

@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
private List<Department> departments; 
+0

實際上,這是oneToMany映射的默認獲取類型,所以它實際上是一種不試圖覆蓋JPA API設計者認爲是個好主意的行爲:) – Gimby

+0

嗨,感謝您的回答,我也使用了懶惰,但是仍然加載100個查詢。我主要想要替代我已經實施的。 – user3157090

1

FetchType.EAGER更改爲FetchType.LAZY。只加載部門當你需要他們這是使用部門

+1

嗨謝謝你的回答,我也用過懶惰,但仍然加載100個查詢。我主要想要替代我已經實施的。 – user3157090

1

經典N + 1問題。 您可以減少批量查詢的數量,它只是將許多懶惰的SQL子句組合爲單個查詢。

例如:

@OneToMany(mappedBy = "employee", cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
@BatchSize(size=10) 
private List<Department> departments;