一.概述
HQL(Hibernate Query Language) 是面向对象的查询语言, 它和 SQL 查询语言有些相似. 在 Hibernate 提供的各种检索方式中, HQL 是使用最广的一种检索方式. 它有如下功能:
在查询语句中设定各种查询条件
- 支持投影查询, 即仅检索出对象的部分属性
- 支持分页查询
- 支持连接查询
- 支持分组查询, 允许使用 HAVING 和 GROUP BY 关键字
- 提供内置聚集函数, 如 sum(), min() 和 max()
- 支持子查询
- 支持动态绑定参数
- 能够调用 用户定义的 SQL 函数或标准的 SQL 函数
@Test
public void testGet() {
//按参数名字绑定
String hql="from Employee e where e.age>:age and e.empName like :name";
Query query= session.createQuery(hql);
query.setInteger(0, 23).setString(1, "%琪%");
//按参数位置绑定
String hql2="from Employee e where e.age>? and e.empName like ?";
Query query2= session.createQuery(hql);
query2.setInteger("age", 23).setString("name", "%琪%");
//遍历结果集合
List<Employee> emp=query.list();
for (Employee employee : emp) {
System.out.println(employee.getEmpName());
}
}
注意:hql语句里的参数都是实体类的,而不是数据库表名的字段
二.分页查询
@Test
public void testLimitGet() {
String hql="from Employee ";
Query query= session.createQuery(hql);
int pageNum=2;//第二页
int pageSize=3;//每页显示三个
List<Employee> employees=query.setFirstResult((pageNum-1)*pageSize)
.setMaxResults(pageSize).list();
for (Employee employee : employees) {
System.out.println(employee);
}
}
三.hql检索方式
我们可以在xml文件中定义一个query放下class外,如下
<query name="queryAge"><![CDATA[from Employee e where e.age >:minAge and e.age<:maxAge]]></query>
通过转义<![CDATA[ ]]>
在程序中通过 Session 的 getNamedQuery() 方法获取查询语句对应的 Query 对象.
@Test
public void testGet() {
Query query=session.getNamedQuery("queryAge");
List<Employee> employees=query.setInteger("minAge", 20).setInteger("maxAge",25).list();
for (Employee employee : employees) {
System.out.println(employee);
}
}
四.投影查询
原始方法:
当我们只需要获取几个字段的信息时候一般把对象放在数组,数组在放在集合中
@Test
public void testFieldGet() {//查询员工名,电话号码与部门信息
String hql="select e.empName,e.tel,e.dept from Employee e where e.dept=?";
Query query=session.createQuery(hql);
Department dept=new Department();
dept.setDeptId(5);
List<Object[]> result=query.setEntity(0, dept).list();
for (Object[] objects : result) {
System.out.println(Arrays.asList(objects));
}
}
测试结果:
投影查询:
@Test
public void testFieldGet() {//查询员工名,电话号码与部门信息
String hql="select new Employee(e.empName,e.tel,e.dept) from Employee e where e.dept=?";
Query query=session.createQuery(hql);
Department dept=new Department();
dept.setDeptId(5);
List<Employee> emp=query.setEntity(0, dept).list();
for (Employee employee : emp) {
System.out.println("员工姓名:"+employee.getEmpName()+";电话:"+employee.getTel()+";部门信息:"+employee.getDept());
}
}
}
new Employee(e.empName,e.tel,e.dept)
//构造函数
public Employee(String empName, String tel, Department dept) {
super();
this.empName = empName;
this.tel = tel;
this.dept = dept;
}
五.报表查询
@Test
public void testGet() {
//查询按部门分类的员工的最大年龄与最小年龄,并且最小年龄>20
String hql="select max(e.age),min(e.age) from Employee e group by e.dept having min(e.age)>?";
Query query=session.createQuery(hql);
List<Object[]> emp=query.setInteger(0, 20).list();
for (Object[] objects : emp) {
System.out.println(Arrays.asList(objects));
}
}
六.HQL连接
使用迫切左外连接
@Test
public void testLeftJoinFetch() {
//迫切左外连接
String hql="select distinct d from Department d left join fetch d.emps";
Query query=session.createQuery(hql);
List<Department> emp=query.list();
System.out.println(emp.size());
for (Department d : emp) {
System.out.println("部门名:"+d.getDeptName()+"-部门人数:"+d.getEmps().size());
}
}
测试结果:
使用迫切内连接
迫切内连接跟迫切左外连接的区别:
跟sql语言的链接一样,区别就是inner一定要包含所有满足条件的结果,而left左边的结果都保留
使用迫切左外连接