执行HQL查询有两种方法,一种是list方法,另一种是iterate方法。这两种方法到底有什么区别,下面我们通过例子来说明两者的区别。
Company表:

Employee表(employee_company_id为外键)

Company实体类:
import java.util.Set;
public class Company {
    private int companyId;
    private String companyName;
    private Set<Employee> companyEmployees;
    public int getCompanyId() {
        return companyId;
    }
    public void setCompanyId(int companyId) {
        this.companyId = companyId;
    }
    public String getCompanyName() {
        return companyName;
    }
    public void setCompanyName(String companyName) {
        this.companyName = companyName;
    }
    public Set<Employee> getCompanyEmployees() {
        return companyEmployees;
    }
    public void setCompanyEmployees(Set<Employee> companyEmployees) {
        this.companyEmployees = companyEmployees;
    }
}Employee实体类:
public class Employee {
    private int employeeId;
    private String employeeName;
    private Company employeeCompany;
    public int getEmployeeId() {
        return employeeId;
    }
    public void setEmployeeId(int employeeId) {
        this.employeeId = employeeId;
    }
    public String getEmployeeName() {
        return employeeName;
    }
    public void setEmployeeName(String employeeName) {
        this.employeeName = employeeName;
    }
    public Company getEmployeeCompany() {
        return employeeCompany;
    }
    public void setEmployeeCompany(Company employeeCompany) {
        this.employeeCompany = employeeCompany;
    }
}Company hbm配置:
<hibernate-mapping> <class name="com.jaeger.hibernatetest.day7.lazy.Company" table="company"> <id name="companyId" column="company_id"> <generator class="native"></generator> </id> <property name="companyName" column="company_name"/> <set name="companyEmployees" cascade="all"> <key column="employee_company_id"></key> <one-to-many class="com.jaeger.hibernatetest.day7.lazy.Employee"/> </set> </class> </hibernate-mapping>
Employee hbm配置:
<hibernate-mapping> <class name="com.jaeger.hibernatetest.day7.lazy.Employee" table="employee"> <id name="employeeId" column="employee_id"> <generator class="native"></generator> </id> <property name="employeeName" column="employee_name"/> <many-to-one name="employeeCompany" class="com.jaeger.hibernatetest.day7.lazy.Company" foreign-key="fk_employee_company" column="employee_company_id" cascade="save-update"> </many-to-one> </class> </hibernate-mapping>
1. list方法
list方法会向数据库发出sql语句,一次查询出所有满足HQL语句的记录,测试方法如下:
List<Employee> allEmployees = session.createQuery("from Employee").list(); //A
for(Employee employee : allEmployees){
    System.out.println(employee.getEmployeeId());
    System.out.println(employee.getEmployeeName());
}A:这里会发出sql去查询满足HQL条件的所有employee信息,sql如下:
select employee0_.employee_id as employee1_1_, employee0_.employee_name as employee2_1_, employee0_.employee_company_id as employee3_1_ from employee employee0_
2. iterate方法
iterate方法只会查询表的主键返回的是Iterator对象,当我们真正使用对象时,才会用主键去数据库查找其他信息,测试方法如下:
Iterator<Employee> allEmployees = session.createQuery("from Employee").iterate(); //A
while(allEmployees.hasNext()){
    Employee employee = allEmployees.next();
    System.out.println(employee.getEmployeeId()); //B
    System.out.println(employee.getEmployeeName()); //C
}A:这里会先去查询employee表的所有主键,sql如下:
select employee0_.employee_id as col_0_0_ from employee employee0_
B:这里会返回employee id,但并不会向数据库发出sql语句,因为employee id为主键,上面已经查询出来了,使用不用在去数据库查询。
C:这里才会根据每个employee id再次去数据库查询其他信息。
select employee0_.employee_id as employee1_1_0_, employee0_.employee_name as employee2_1_0_, employee0_.employee_company_id as employee3_1_0_ from employee employee0_ where employee0_.employee_id=?
总结:list方法只会查询一次,而iterate方法先会去查所有主键,再遍历主键去查询其他信息,所以总共会查询N+1次。当我们的程序要根据主键再来做不同处理的话,比如:if(employee.getEmployeeId() == 1),应该使用iterate,因为只取主键的话不会再发sql语句了,也会使加载数据大大减少。但如果要遍历所有信息的话,应该用list方法,可以一次加载所有信息,不用频繁的与数据库通信。
本文出自 “銅鑼衛門” 博客,请务必保留此出处http://jaeger.blog.51cto.com/11064196/1750727
原文:http://jaeger.blog.51cto.com/11064196/1750727