执行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方法,可以一次加载所有信息,不用频繁的与数据库通信。
时间: 2024-10-13 09:21:56