Hibernate HQL查询
Hibernate检索对象的方式
- 导航对象图检索方式:根据已经加载的对象导航到其它对象。
- OID:按照对象的OID来进行检索。
- HQL:使用面向对象的HQL查询语言。
- QBC:使用QBC(Query by criteria) API来检索对象。这种API封装了基于字符串形式的查询语句。提供了更加面向对象的查询接口。
- SQL:使用本地数据的SQL查询语句。
HQL检索方式
HQL(Hibernate Query Language)是面向对象的查询语言。它和SQL查询语言有些相似,在Hibernate提供的各种检索方式中,HQL是使用最广泛的一种检索方式,它有如下的功能:
- 在查询语句中指定各种查询条件。
- 支持投影查询,即仅检索出对象的部分属性。
- 支持分页查询。
- 支持连接查询。
- 支持分组查询,如使用GROUP BY和HAVING子句。
- 提供内置聚集函数,如max和min。
- 支持子查询。
- 支持动态绑定参数。
- 能够调用用户定义的SQL函数或标准的SQL函数。
HQL检索包含以下几个步骤:
- 通过Session的createQuery方法创建一个Query对象,它包含一个HQL查询语句,HQL查询语句可以包含命名参数。
- 动态绑定参数。
- 调用Query相关方法指定查询语句。
Query接口支持方法链编程风格,它的setXxx方法返回自身实例,而不是void类型。
HQL vs SQL:
- HQL是面向对象的,Hibernate负责解析HQL语句。然后根据对象关系映射文件中的映射信息,把HQL翻译成相应的SQL语句。HQL查询语句中的主体是域模型中的类以及类的属性。
- SQL查询语句是与关系型数据库绑定在一起的,SQL查询语句中的主体是数据库表及表的字段。
绑定参数:
Hibernate的参数绑定机制依赖于JDBC API中的PrepareStatement的预定义SQL语句的功能。
HQL的参数绑定有两种形式:
- 按参数名字进行绑定:在HQL查询语句中定义命名参数,命名参数以“:”开头。
- 按参数位置绑定:在HQL查询语句中使用?来定义参数的设置。
相关方法:
- setEntity():把参数与一个持久类绑定。
- setParameter():绑定任意类型的参数,该方法的第三个参数是指定Hibernate映射类型。
HQL采用ORDERBY关键字对查询结果进行排序。
HQL查询实例
按照参数位置进行绑定
String hql = "from Student where school = ?0 ";
//Create query object.
Query query = session.createQuery(hql);
//Bind parameters.
query.setParameter(0, "University");
//Execute query.
List<Student>students = query.list();
System.out.println(students.size());
按照参数名进行绑定
String hql = "from Student where school = :school ";
//Create query object.
Query query = session.createQuery(hql);
//Bind parameters.
query.setParameter("school", "University");
//Execute query.
List<Student>students = query.list();
System.out.println(students.size());
Query对象使用setXxx方法,支持方法链的编程风格。使用方法链的实例如下:
String hql = "from Student where school = :school and name like :name ";
//Create query object.
Query query = session.createQuery(hql);
//Bind parameters.
query.setParameter("school", "University")
.setParameter("name", "%HFR%");
//Execute query.
List<Student>students = query.list();
System.out.println(students.size());
分页查询
- setFirstResult(int firstResult):设定从那一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引的位置。索引位置的起始值为0。默认情况下Query从查询结果中的第一个对象开始检索。
- setMaxResults(int maxResults):设定一次最多检索出的对象的数目。在默认情况下,Query和Criteria接口检索出查询结果的所有对象。
示例:
String hql = "from Student";
int pageNo = 3;
int pageSize = 5;
Query query = session.createQuery(hql);
List<Student>students = query.setFirstResult((pageNo - 1) * pageSize)
.setMaxResults(pageSize)
.list();
System.out.println(students.get(0).getName());
命名查询
将HQL语句定义在hbm.xml文件中。便于维护。修改的时候不需要打开源代码
示例:
Person.hbm.xml
<query name="byName">From Student where name = :name</query>
测试类:
Query query = session.getNamedQuery("byName");
List<Student>students = query.setParameter("name", "HFR_STU").list();
System.out.println(students.size());
投影查询
查询结果仅包含实体的部分属性。通过Select关键字实现。
可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录。使程序代码能完全利用面向对象的语义来访问查询结果集。
可以通过Distinct关键字保证查询结果集没有重复的元素。
示例:
String hql = "select id, name, school from Student where name = :name ";
Query query = session.createQuery(hql);
List<Object[]>results = query.setParameter("name", "HFR_STU").list();
for(Object[] result: results){
System.out.println(Arrays.asList(result));
}
我们可以改善这个方法:直接通过SQL语句检索出一个对象。但此时我们需要给需要查询的对象加上构造函数
public class Student extends Person {
private String school;
public Student() {
}
public Student(Integer id, String name, String school) {
super(id, name);
this.school = school;
}
}
之后是测试类
String hql = "select new Student(id, name, school) from Student where name = :name ";
Query query = session.createQuery(hql);
List<Student>results = query.setParameter("name", "HFR_STU").list();
for(Student result: results){
System.out.println(Arrays.asList(result.getId() + "; " + result.getName() + "; " + result.getSchool()));
}
报表查询
报表查询用于对数据分组和统计。与SQL一样,HQL通过GROUP BY关键字对数据进行分组,用HAVING关键字对分组数据设定约束条件。
在HQL查询中可以使用以下聚集函数:
- count()
- min()
- max()
- sum()
- avg()
示例:
String hql = "select min(salary), max(salary) from employee "
+"group by dept "
+"having min(salary) > :minSal";
Query query = session.createQuery(hql).setParameter("minSal", 10000);
List<Object[]>results = query.list();
for(Object[] result: results){
System.out.println(Arrays.asList(result));
}
HQL迫切左外连接与左外连接的区别
迫切左外连接
使用LEFT JOIN FETCH关键字表示迫切左外连接。
list()方法返回集合中存放的实体对象的引用。查询结果中可能存在重复的对象。可以通过HashSet过滤重复的元素。
左外连接
LEFT JOIN关键字表示左外连接。
list()方法返回的是集合中存放的对象数组类型。根据配置文件决定集合的检索策略。
关联级别运行时的检索策略
如果在HQL中没有显示的指定检索策略,将使用映射文件配置的检索策略。
HQL会忽视映射文件中设置的迫切左外连接的检索策略,如果希望HQL采用迫切左外连接的检索策略,就必须在HQL语句中显示指定它。
若在HQL代码中显示指定了检索策略,就会覆盖映射文件中配置的检索策略。