Hibernate中提供了多种检索对象的方式,主要包括以下种类:

  1. 导航对象图检索方式:根据已经加载的对象导航到其他对象
  2. OID检索方式:根据对象的OID来检索对象
  3. HQL检索方式:使用面向对象的HQL查询语言
  4. QBC检索方式:使用QBC(Query By Criteria)API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口
  5. 本地SQL检索方式:使用本地数据库的SQL查询语句

本文主要介绍第三种方式,也就是HQL检索对象。

HQL(Hibernate Query Language)是面向对象的查询语言,它和SQL查询语言有些相似。在Hibernate提供的各种检索方式中,HQL是使用最广的一种检索方式。它有如下功能:

  • 在查询语句中设定各种查询条件
  • 支持投影查询,即仅检索出对象的部分属性
  • 支持分页查询
  • 支持连接查询
  • 支持分组查询,允许使用HAVING和GROUP BY关键字
  • 提供内置聚集函数,如sum(), min()和max()
  • 支持子查询
  • 支持动态绑定参数
  • 能够调用用户定义的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中的PreparedStatement的预定义SQL语句功能
  • Hibernate的参数绑定有两种形式:

    1.按参数名字绑定:在HQL查询语句中定义命名参数,命名参数以":"开头

    2.按参数位置绑定:在HQL查询语句中用"?"来定义参数位置

  • 相关方法:

    1.setEntity():把参数与一个持久化类绑定

    2.setParameter(): 绑定任意类型的参数,该方法的第三个参数显式指定Hibernate映射类型

  • HQL采用ORDER BY关键字对查询结果排序

下面详细介绍下Hibernate的HQL的几个功能:

分页查询:

  • setFirstResult(int firstResult): 设定从哪一个对象开始检索,参数firstResult表示这个对象在查询结果中的索引位置,索引位置的起始值为0.默认情况下,Query从查询结果中的第一个对象开始检索
  • setMaxResult(int maxResults): 设定一次最多检索出的对象的数目。在默认情况下,Query和Criteria接口检索出查询结果中所有的对象

在映射文件中定义命名查询语句

  • Hibernate允许在映射文件中定义字符串形式的查询语句
  • <query>元素用于定义一个HQL查询语句,它和<class>元素并列

    <query name="salaryEmps"><![CDATA[FROM Employee w WHERE e.salary > :minSal AND e.salary < :maxSal]]></query>

  • 在程序中通过Session的getNamedQuery()方法获取查询语句对应的Query对象

投影查询

  • 投影查询:查询结果仅包含实体的部分属性。通过SELECT关键字实现
  • Query的list()方法返回的集合中包含的是数组类型的元素,每个对象数组代表查询结果的一条记录
  • 可以在持久化类中定义一个对象的构造器来包装投影查询返回的记录,使程序代码能完全运用面向对象的语义来访问查询结果集
  • 可以通过DISTINCT关键字来保证查询结果不会返回重复元素

报表查询

  • 报表查询用于对数据分组和统计,与SQL一样,HQL利用GROUP BY关键字对数据分组,用HAVING关键字对分组数据设定约束条件
  • 在HQL查询语句中可以调用以下聚集函数
    • count()
    • min()
    • max()
    • sum()
    • avg()  

HQL(迫切)左外连接

  • 迫切左外连接:

    • LEFT JOIN FETCH关键字表示迫切左外连接检索策略
    • list()方法返回的集合中存放实体对象的引用,每个Department对象关联的Employee集合都被初始化,存放所有关联的Employee的实体对象
    • 查询结果中可能会包含重复元素,可以通过一个HashSet来过滤重复元素

  • 左外连接:
    • LEFT JOIN关键字表示左外连接
    • list()方法返回的集合中存放的是对象数组类型
    • 根据配置文件来决定Employee集合的检索策略
    • 如果希望list()方法返回的集合中仅包含Department对象,可以在HQL查询语句中使用SELECT关键字

HQL(迫切)内连接

  • 迫切内连接:

    • INNER JOIN FETCH关键字表示迫切内连接,也可以省略INNER关键字
    • list()方法返回的集合中存放Department对象的引用,每个Department对象的Employee集合都被初始化,存放所有关联的Employee对象
  • 内连接
    • INNER JOIN关键字表示内连接,也可以省略INNER关键字
    • list()方法的集合中存放的每个元素对应查询结果的一条记录,每个元素都是对象数组类型
    • 如果希望list()方法的返回的集合仅包含Department对象,可以在HQL查询语句中使用SELECT关键字

关联级别运行时的检索策略:

  • 如果在HQL中没有显式指定检索策略,将使用映射文件配置的检索策略
  • HQL会忽略映射文件中设置的迫切左外连接检索策略,如果希望HQL采用迫切左外连接策略,就必须在HQL查询语句中显式指定它
  • 若在HQL代码中显式指定了检索策略,就会覆盖映射文件中配置的检索策略

==============================代码区========================================

Department.java

 package com.yl.hibernate.entities;

 import java.util.HashSet;
import java.util.Set; public class Department { private Integer id;
private String name; private Set<Employee> emps = new HashSet<Employee>(); public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public Set<Employee> getEmps() {
return emps;
} public void setEmps(Set<Employee> emps) {
this.emps = emps;
} @Override
public String toString() {
//return "Department [id=" + id + ", name=" + name + "]";
return "Department [id=" + id + "]";
} }

Employee.java

 package com.yl.hibernate.entities;

 public class Employee {

     private Integer id;
private String name;
private float salary;
private String email; private Department dept; public Integer getId() {
return id;
} public void setId(Integer id) {
this.id = id;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
} public float getSalary() {
return salary;
} public void setSalary(float salary) {
this.salary = salary;
} public String getEmail() {
return email;
} public void setEmail(String email) {
this.email = email;
} public Department getDept() {
return dept;
} public void setDept(Department dept) {
this.dept = dept;
} @Override
public String toString() {
return "Employee [id=" + id + "]";
} public Employee(){} public Employee(String email, float salary, Department dept) {
super();
this.salary = salary;
this.email = email;
this.dept = dept;
} }

Department.hbm.xml

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-12-1 19:29:32 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.yl.hibernate.entities.Department" table="YL_DEPARTMENT">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<set name="emps" table="YL_EMPLOYEE" inverse="true" lazy="true">
<key>
<column name="DEPT_ID" />
</key>
<one-to-many class="com.yl.hibernate.entities.Employee" />
</set>
</class>
</hibernate-mapping>

Employee.hbm.xml

 <?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<!-- Generated 2014-12-1 19:29:32 by Hibernate Tools 3.4.0.CR1 -->
<hibernate-mapping>
<class name="com.yl.hibernate.entities.Employee" table="YL_EMPLOYEE">
<id name="id" type="java.lang.Integer">
<column name="ID" />
<generator class="native" />
</id>
<property name="name" type="java.lang.String">
<column name="NAME" />
</property>
<property name="salary" type="float">
<column name="SALARY" />
</property>
<property name="email" type="java.lang.String">
<column name="EMAIL" />
</property>
<many-to-one name="dept" class="com.yl.hibernate.entities.Department" fetch="join">
<column name="DEPT_ID" />
</many-to-one>
</class> <query name="salaryEmps"><![CDATA[FROM Employee e WHERE e.salary > :minSal AND e.salary < :maxSal]]></query> </hibernate-mapping>

测试类:

 package com.yl.hibernate.test;

 import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Set; import oracle.net.aso.e; import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.junit.After;
import org.junit.Before;
import org.junit.Test; import com.yl.hibernate.entities.Department;
import com.yl.hibernate.entities.Employee; public class HibernateTest { private SessionFactory sessionFactory;
private Session session;
private Transaction transaction; @Before
public void init() {
Configuration configuration = new Configuration().configure();
ServiceRegistry serviceRegistry =
new ServiceRegistryBuilder().applySettings(configuration.getProperties())
.buildServiceRegistry(); sessionFactory = configuration.buildSessionFactory(serviceRegistry); session = sessionFactory.openSession(); transaction = session.beginTransaction();
}
@After
public void destory() {
transaction.commit(); session.close(); sessionFactory.close();
} @Test
public void testHQL() {
//1.创建 Query 对象
//基于位置参数
String hql = "FROM Employee e WHERE e.salary > ? AND e.email LIKE ? AND e.dept = ? ORDER BY e.salary";
Query query = session.createQuery(hql);
//2.绑定参数
//Query 对象调用setXxx()方法支持方法链的编程风格
Department dept = new Department();
dept.setId(30);
query.setFloat(0, 2000)
.setString(1, "%A%")
.setEntity(2, dept);
//3.执行查询
List<Employee> emps = query.list();
System.out.println(emps);
} @Test
public void testHQLNamedParameter() {
//1.创建 Query 对象
//基于命名参数
String hql = "FROM Employee e WHERE e.salary > :sal AND e.email LIKE :email";
Query query = session.createQuery(hql);
//2.绑定参数
query.setFloat("sal", 2000)
.setString("email", "%A%");
//3.执行查询
List<Employee> emps = query.list();
System.out.println(emps.size());
}
/**
* 分页查询
*/
@Test
public void testPageQuery() {
String hql = "FROM Employee";
Query query = session.createQuery(hql); int pageNo = 3;
int pageSize = 5; List<Employee> employees = query.setFirstResult((pageNo-1) * pageSize)
.setMaxResults(pageSize)
.list();
System.out.println(employees); }
/**
* 在映射文件中定义命名查询语句
*/
@Test
public void testNamedQuery() {
Query query = session.getNamedQuery("salaryEmps"); List<Employee> emps = query.setFloat("minSal", 2000)
.setFloat("maxSal", 3000)
.list();
System.out.println(emps); }
/**
* 投影查询
*/
@Test
public void testFieldQuery() {
String hql = "SELECT e.email, e.salary, e.dept FROM Employee e WHERE e.dept = :dept";
Query query = session.createQuery(hql); Department dept = new Department();
dept.setId(20);
List<Object[]> result = query.setEntity("dept", dept).list(); for (Object[] objects : result) {
System.out.println(Arrays.asList(objects));
} } /**
* 投影查询
*/
@Test
public void testFieldQuery2() {
String hql = "SELECT new Employee(e.email, e.salary, e.dept) "
+ "FROM Employee e "
+ "WHERE e.dept = :dept"; Query query = session.createQuery(hql); Department dept = new Department();
dept.setId(20);
List<Employee> result = query.setEntity("dept", dept).list(); for (Employee emp : result) {
System.out.println(emp.getId() + ", " + emp.getEmail() + ", " + emp.getSalary() + ", " + emp.getDept());
} } @Test
public void testGroupBy() {
String hql = "SELECT min(e.salary), max(e.salary) "
+ "FROM Employee e "
+ "GROUP BY e.dept "
+ "HAVING min(salary) > :minSal";
Query query = session.createQuery(hql)
.setFloat("minSal", 700); List<Object[]> result = query.list();
for (Object[] objects : result) {
System.out.println(Arrays.asList(objects));
}
}
/**
* 迫切左外连接
*/
@Test
public void testLeftJoinFetch() {
/*String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN FETCH d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
System.out.println(depts.size());*/ String hql = "FROM Department d LEFT JOIN FETCH d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
depts = new ArrayList<Department>(new LinkedHashSet<Department>(depts)); System.out.println(depts.size()); for (Department department : depts) {
System.out.println(department.getName() + "-" + department.getEmps().size());
}
} @Test
public void testLeftJoin() {
/*String hql = "FROM Department d LEFT JOIN d.emps";
Query query = session.createQuery(hql); List<Object[]> result = query.list();
System.out.println(result); for (Object[] objects : result) {
System.out.println(Arrays.asList(objects));
}*/ String hql = "SELECT DISTINCT d FROM Department d LEFT JOIN d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
System.out.println(depts.size()); for (Department department : depts) {
System.out.println(department.getName() + ", " + department.getEmps().size());
}
} @Test
public void testInnerJoinFetch() {
/*String hql = "SELECT DISTINCT d FROM Department d INNER JOIN FETCH d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
System.out.println(depts.size());*/ String hql = "FROM Department d INNER JOIN FETCH d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
depts = new ArrayList<Department>(new LinkedHashSet<Department>(depts)); System.out.println(depts.size()); for (Department department : depts) {
System.out.println(department.getName() + "-" + department.getEmps().size());
}
} @Test
public void testInnerJoin() {
/*String hql = "FROM Department d INNER JOIN d.emps";
Query query = session.createQuery(hql); List<Object[]> result = query.list();
System.out.println(result); for (Object[] objects : result) {
System.out.println(Arrays.asList(objects));
}*/ String hql = "SELECT DISTINCT d FROM Department d INNER JOIN d.emps";
Query query = session.createQuery(hql); List<Department> depts = query.list();
System.out.println(depts.size()); for (Department department : depts) {
System.out.println(department.getName() + ", " + department.getEmps().size());
}
} }

Hibernate之HQL介绍的更多相关文章

  1. [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,

    本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...

  2. hibernate的hql查询

    1.概念介绍 1.Query是Hibernate的查询接口,用于从数据存储源查询对象及控制执行查询的过程,Query包装了一个HQL查询语句. 2.HQL是Hibernate Query Langua ...

  3. Hibernate五 HQL查询

    HQL查询一 介绍1.HQL:Hibernate Query Language,是一种完全面向对象的查询语言.使用Hibernate有多重查询方式可供选择:hibernate的HQL查询,也可以使用条 ...

  4. Hibernate学习-Hibernate查询语言HQL

    HQL(Hibernate Query Language)Hibernate查询语言,语法类似于SQL,可以直接使用实体类及属性. 使用HQL 可以避免使用JDBC 查询的一些弊端 不需要再编写繁复的 ...

  5. Hibernate之HQL查询

    一.Hibernate 提供了以下几种检索对象的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 HQL 检索方式:使用面向对象的 H ...

  6. Hibernate学习---基本介绍+作用+配置

    从今天开始重新学习(以前学的太匆忙)Hibernate,这篇文章主要就一下几点进行讲解和说明: Hibernate的基本介绍 Hibernate的作用 Hibernate基本配置 Hibernate的 ...

  7. Hibernate 的hql查询简介【申明:来源于网络】

    Hibernate 的hql查询简介[申明:来源于网络] Hibernate 的hql查询简介:http://blog.csdn.net/leaf_130/article/details/539329 ...

  8. Hibernate的hql语句save,update方法不执行

    Hibernate的hql语句save,update方法不执行 可能出现的原因问题: 未进行事务管理 需要进行xml事务配置或者注解方式的事务配置

  9. Hibernate学习---第九节:Hibernate之hql

    一.Hql 入门 1.实体类: package learn.hibernate.bean; import java.util.Date; import java.util.HashSet; impor ...

随机推荐

  1. [译] ASP.NET 生命周期 – ASP.NET 上下文对象(八)

    使用 HttpResponse 对象 HttpResponse 对象是与 HttpRequest 对象相对应的,用来表示构建中的响应.它当中提供了方法和属性可供我们自定义响应,有一些在使用 MVC 视 ...

  2. DataTable经典报错{列/行已属于其他表}

    Delete()之后需要datatable.AccepteChanges()方法确认完全删除,因为Delete()只是将相应列的状态标志为删除, 还可以通过datatable.RejectChange ...

  3. iOS视频压缩存储至本地并上传至服务器-b

    最近做了一个项目,我把其中的核心功能拿出来和大家分享一下,重点还是自己梳理一下. 这里关于视频转码存储我整理了两个方法,这两个方法都是针对相册内视频进行处理的. 1.该方法没有对视频进行压缩,只是将视 ...

  4. coolcarousel 图片轮播缩放问题

    var myurl; var mydata; var mytype = "POST"; var jsonType = "json"; var htmlType ...

  5. mysql 增加删除用户

    mysql 增加用户 (注意:因为MYSQL环境中的命令,所以后面都带一个分号作为命令结束符) 格式:grant select on 数据库.* to 用户名@登录主机 identified by ' ...

  6. CSS样式表引用方式

    最近讲课中,有些学员对调用样式表老是有含糊不清?大体说来有四种方式: 1.外部文件引用方式;(推荐使用) 2.使用@import引用外部CSS文件; 3.内部文档头方式也叫内嵌法调用; 4.直接插入式 ...

  7. ie6 iframe src="javascript:" 报安全警报问题

    <iframe id="shuaka_iframe" class="embed-page-iframe" data-src="https://w ...

  8. [Ruby on Rails系列]3、初试Rails:使用Rails开发第一个Web程序

    本系列前两部分已经介绍了如何配置Ruby on Rails开发环境,现在终于进入正题啦! Part1.开发前的准备 本次的主要任务是开发第一个Rails程序.需要特别指出的是,本次我选用了一个(Paa ...

  9. hdu 4678 Mine 博弈论

    这是一题简单的博弈论!! 所有的空白+边界的数字(个数为n)为一堆,容易推出其SG函数值为n%2+1: 其他所有的数字(个数为m)的SG值为m%2. 再就是用dfs将空白部分搜一下即可!(注意细节) ...

  10. poj 1095 Trees Made to Order 卡特兰数

    这题用到了卡特兰数,详情见:http://www.cnblogs.com/jackge/archive/2013/05/19/3086519.html 解体思路详见:http://blog.csdn. ...