执行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=?
总结:
1. list方法只会查询一次,而iterate方法先会去查所有主键,再遍历主键去查询其他信息,所以总共会查询N+1次。当我们的程序要根据主键再来做不同处理的话,比如:if(employee.getEmployeeId() == 1),应该使用iterate,因为只取主键的话不会再发sql语句了,也会使加载数据大大减少。但如果要遍历所有信息的话,应该用list方法,可以一次加载所有信息,不用频繁的与数据库通信。
2. list方法查询实体对象返回的就是相应的对象,而iterate返回的则是相应对象的代理对象。
3. list和iterate在session缓存方面还有些区别,可以参考这篇文章:Hibernate一级缓存。
转载于:https://blog.51cto.com/jaeger/1750727