JPA一对多关系查询

时间:2014-03-06 10:02:29

标签: java sql hibernate 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>

4 个答案:

答案 0 :(得分:4)

这是典型的N+1 selects issue。我通常使用described herehere

JOIN FETCH次查询解决此问题

答案 1 :(得分:1)

您可以将fetchtype切换为lazy,这将导致仅在必要时查询部门。

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

答案 2 :(得分:1)

FetchType.EAGER更改为FetchType.LAZY。仅在需要时加载部门,例如循环employee.getDepartmentList()

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

在使用部门之前

答案 3 :(得分:1)

经典N + 1问题。 您可以使用Batch Fetching减少查询次数,这只会将许多惰性sql子句组合成单个。

例如:

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