Hibernate之HQL介绍
Hibernate中提供了多种检索对象的方式,主要包括以下种类:
- 导航对象图检索方式:根据已经加载的对象导航到其他对象
- OID检索方式:根据对象的OID来检索对象
- HQL检索方式:使用面向对象的HQL查询语言
- QBC检索方式:使用QBC(Query By Criteria)API来检索对象。这种API封装了基于字符串形式的查询语句,提供了更加面向对象的查询接口
- 本地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介绍的更多相关文章
- [原创]java WEB学习笔记89:Hibernate学习之路-- -Hibernate检索方式(5种),HQL介绍,实现功能,实现步骤,
本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱 ...
- hibernate的hql查询
1.概念介绍 1.Query是Hibernate的查询接口,用于从数据存储源查询对象及控制执行查询的过程,Query包装了一个HQL查询语句. 2.HQL是Hibernate Query Langua ...
- Hibernate五 HQL查询
HQL查询一 介绍1.HQL:Hibernate Query Language,是一种完全面向对象的查询语言.使用Hibernate有多重查询方式可供选择:hibernate的HQL查询,也可以使用条 ...
- Hibernate学习-Hibernate查询语言HQL
HQL(Hibernate Query Language)Hibernate查询语言,语法类似于SQL,可以直接使用实体类及属性. 使用HQL 可以避免使用JDBC 查询的一些弊端 不需要再编写繁复的 ...
- Hibernate之HQL查询
一.Hibernate 提供了以下几种检索对象的方式: 导航对象图检索方式: 根据已经加载的对象导航到其他对象 OID 检索方式: 按照对象的 OID 来检索对象 HQL 检索方式:使用面向对象的 H ...
- Hibernate学习---基本介绍+作用+配置
从今天开始重新学习(以前学的太匆忙)Hibernate,这篇文章主要就一下几点进行讲解和说明: Hibernate的基本介绍 Hibernate的作用 Hibernate基本配置 Hibernate的 ...
- Hibernate 的hql查询简介【申明:来源于网络】
Hibernate 的hql查询简介[申明:来源于网络] Hibernate 的hql查询简介:http://blog.csdn.net/leaf_130/article/details/539329 ...
- Hibernate的hql语句save,update方法不执行
Hibernate的hql语句save,update方法不执行 可能出现的原因问题: 未进行事务管理 需要进行xml事务配置或者注解方式的事务配置
- Hibernate学习---第九节:Hibernate之hql
一.Hql 入门 1.实体类: package learn.hibernate.bean; import java.util.Date; import java.util.HashSet; impor ...
随机推荐
- docker下PHP+Nginx+HHVM运行环境
Dockerfile 准备开始,我们创建一个 Dockerfile —— Dockerfile 包含如何创建所需镜像的指令. FROM centos:centos6MAINTAINER Mike ...
- mac 下 sphinx + mysql + php 实现全文搜索(xampp)(3)sphinx 的配置项解析
source:数据的来源,数据是从什么地方来的. index:索引,当有数据源之后,从数据源处构建索引.索引实际上就是相当于一个字典检索.有了整本字典内容以后,才会有字典检索. searchd:提供搜 ...
- Linux安装oracle 10g常见问题之——OUI-25031
OUI-25031:Some of the configuration assistants failed/cancelled. 这是安装过程中常见的错误之一. 引起此错误的原因:/etc/hosts ...
- EXTJS4.2 后台管理菜单栏
EXTJS 代码: 第一种方法: { title: '汽车信息管理', layout: 'fit', items: [ { xtype: 'treepanel', border: 0, rootVis ...
- python中变量
在Python中,变量的概念基本上和初中代数的方程变量是一致的. 例如,对于方程式 y=x*x ,x就是变量.当x=2时,计算结果是4,当x=5时,计算结果是25. 只是在计算机程序中,变量不仅可以是 ...
- jq 7种实例化
$(html) ->$(array) $(html,{}||$(...)) $(#id) $(expr,$(...)) $(expr,context) $(dom) $(function(){} ...
- ExtJs gridPanel Column 时间格式化
var panel = new Ext.container.Viewport({ items: { xtype: 'gridpanel', id: 'gridPanel', store: store, ...
- ExtJS4.2学习(12)基于表格的右键菜单(转)
鸣谢:http://www.shuyangyang.com.cn/jishuliangongfang/qianduanjishu/2013-11-24/181.html --------------- ...
- where, group by, having
where vs having 当一个sql语句中存在where子句,会先执行where,然后执行group by,然后执行having. 一般来说,only use 'having' when yo ...
- SQL手工注入
site:xx.cn inurl:asp?id= //找文章 xx.cn/pth/onews.asp?id=243' //试注入 xx.cn/pth/onews.asp?id=243 order b ...