1. Hibernate查询介绍
Hibernate HQL查询、Criteria查询、调用存储过程
Hibernate事务管理和并发控制
Hibernate 延迟加载策略、抓取策略、一级二级缓存管理
Hibernate整合Struts
2. HQL介绍
HQL:Hibernate查询语言,它是Hibernate提供的一种面向对象的查询语言。
(1)在查询语句中设定各种查询条件
(2)支持动态绑定参数(类似sql语句中的预处理,?赋值)
(3)支持投影查询(纵向查询,后面会举例具体说明)、分页查询、连接查询、分组查询,子查询
(4) 内置了一些聚集函数
Hibernate中的Query接口就是专门用来执行HQL语句的查询接口。
HQL查询的主要步骤:
《1》.创建查询对象
Query query=session.createQuery(“from Dept”);
《2》.执行查询列出结果
1)列出所有的结果
List<Dept> depts=query.list();
for(Dept dept:depts){…}
2)列出单个结果
Query query=session.createQuery(“from Dept where id=1”);
query.setMaxResults(1);
Dept dept=(Dept)query.uniqueResult();
3)迭代访问结果;使用情况较少,麻烦
Iterator<Dept> it=query.iterate();
While(it.hasnext()){
}
3. HQL基本语法:持久化类名区分大小写
1)选择要查询的持久化类。
String hql=“from Dept”
Query query=session.createQuery(hql);
String hql=“from Dept as d”;
as是其别名的意思,可以省略,后面举例会具体说明
2).针对选定属性创建一个类,提供以这两个属性为参数的构造方法,使用此类来封装查询结果。
3)where 条件子句
• String hqlString="from Dept d where d.createdTime>='2010-01-01'";
• Query query=session.createQuery(hqlString);
• String hqlString="from Dept d where d.name like'java%' and d.employees is not empty and d.createdTime<current_date()";
4). 绑定查询参数
• 按参数名字绑定,这里用到了方法链
String hql=“from Dept where id>:id and name like:likeName”
List<Dept> dept=session.createQuery(hql).setLong(“id”,new Long(ingputID)).setString(“likeName”,”%”+inputName+”%”).list();
5)distinct 过滤重复值
Select distinct createTime from Dept
6)聚集函数(计数)
select count(id) from Dept d
7)order by 排序(asc升序,desc降序)
From Dept d order by d.createdTime asc,d.name desc
8)group by 对记录分组
Select count(e) from Employee e group by e.dept;
9)having 对分组后数据进行条件过滤
Select e.dept.name from Eployee e group by e.dept having count(e)>1
4.其他知识点
分页查询
Query接口提供两个用于分批显示查询结果的方法
setFirstResult(int firstResult):在记录集中从第几条记录开始取数据。默认是0。
session.beginTransaction();
String hql = "from Employee";
List<Employee> empls = session.createQuery(hql).setMaxResults(pageSize) .setFirstResult((pageNo - 1) * pageSize).list();
session.getTransaction().commit();
setMaxResults(int maxResults):设置每次查询返回的最大对象数。
批量修改和删除:直接通过SQL语句操作数据库,执行完后,当前session缓存中的数据与数据库中的数据不是同步的。
String hql=“delete Dept as d where d.name like:likeName”;
Query query=session.createQuery(hql).setString(“likeName”,”%三%”);
int count= query.executeUpdate();
连接查询
• Inner join (内连接) left outer join(左外连接)
• Right outer join (右外连接) full join(全连接)
String hql = "FROM Dept d JOIN d.employees e "
+ " WHERE d.name LIKE :likeName";
抓取连接查询 fetch与懒加载相对
抓取:是指从数据库加载一个对象数据时,同时把它所关联的对象和集合的数据一起加载出来,以便减少SQL语句的数据,从而提高查询效率。
From Dept d left join Fetch d.employees e where d.name like “%web%”
5. 以上知识点的案例的分析
package com.hbsi.one2many;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.hibernate.Query;
import org.hibernate.Session;
import org.junit.Test;
import com.hbsi.utils.HibernateSessionFactory;
public class AppHql {
@Test
public void find(){
Session session = HibernateSessionFactory.getSession();
/*//简单查询,返回结果为list
Query query = session.createQuery("from Department");
List<Department> list = query.list();
for(Department dep : list){
System.out.println(dep.getDepId()+"---"+dep.getDepName());
}
*/
/*//简单查询,返回结果为类对象
String hql = "from Department where id>1";
//setMaxResults(1)是设置最大查询结果为1 ,否则你后面用的uniqueResult()方法会出错,改方法返回的结果是唯一值。
Query query = session.createQuery(hql).setMaxResults(1);
Department dep = (Department) query.uniqueResult();
System.out.println(dep.getDepId()+"---"+dep.getDepName());
*/
/*//投影查询(即纵向查询,就是查找某一字段的记录),选择部分属性,list中的元素是:object[];由于使用较麻烦,所以实际开发中不建议使用映射查询
String hql = "select depId,depName from Department";
Query query = session.createQuery(hql);
List list = query.list();
for(int i=0;i<list.size();i++){
Object[] obj = (Object[]) list.get(i);
System.out.println(obj[0]+"---"+obj[1]);
System.out.println("-----------------");
}*/
/*//通过一个类来封装部分查询的结果,简化操作,但是执行效率不高
String hql = "select new com.hbsi.one2many.DepartRow(d.depId,d.depName) from Department d";
Query query = session.createQuery(hql);
List<DepartRow> list = query.list();
for(DepartRow dr : list){
System.out.println(dr.getId()+"-----"+dr.getName());
}*/
/*//查询某一个属性的时候不需要再封装多余的属性类了,直接返回一个该属性类型的list
String hql = "select depName from Department";
Query query = session.createQuery(hql);
List<String> list = query.list();
for(String s : list){
System.out.println(s);
}*/
/*//查询包含员工的部门 is empty的应用
String hql = "from Department d where d.emp is not empty ";
Query query = session.createQuery(hql);
List<Department> list = query.list();
for(Department d : list){
System.out.println(d.getDepName());
for(Employee e : d.getEmp()){
System.out.println("|----"+e.getEmpName());
}
}*/
//绑定查询参数 : ?的下标由0开始
/*String hql = "from Department d where d.depId>? and depName=?";
Query query = session.createQuery(hql);
query.setInteger(0,1);
query.setString(1,"软件系");
List<Department> dep = query.list();
for(Department d : dep){
System.out.println(d.getDepId()+"----"+d.getDepName());
}*/
//通过名字 (:名字)这种方法是给条件赋名称的方法来避免不知道哪个问号赋的什么值
/*String hql = "from Department d where d.depId>:ids and depName=:name";
Query query = session.createQuery(hql).setInteger("ids",1).setString("name","软件系");
List<Department> dep = query.list();
for(Department d : dep){
System.out.println(d.getDepId()+"----"+d.getDepName());
}
*/
//统计部门数,一般通过统计id数来达到功能,不推荐使用count(*);下面两种方法的后台sql语句一样
/*String hql = "select count(depId) from Department";
Query query = session.createQuery(hql);
//方法一:通过获取总记录数统计
List list = query.list();
System.out.println(list.get(0));
//方法二:uniqueResult方法获取到的是Lang类型,不是Integer类型,强转为Integer类型会出错
Long dep = (Long) query.uniqueResult();
System.out.println(dep);*/
//统计各个部门员工人数 部门名 ,人数 ;这里统计的是人数,不是部门数
/*String hql = "select e.dep.depName,count(e.empId) from Employee e group by e.dep having count(e.empId)>=1";
Query query = session.createQuery(hql);
List list = query.list();
for(int i=0;i<list.size();i++){
Object[] obj = (Object[]) list.get(i);
System.out.print(obj[0]+"--");
System.out.println(obj[1]);
}*/
//用hql语句删除用户,这里的hql删除的是数据库表中的数据,但是session缓存中还保留着数据;这里调用的是executeUpdate更新语句,所以要开启事务,否则会回滚导致数据库的数据也没有被删除
/*session.beginTransaction();
Employee e = (Employee) session.get(Employee.class,6);
System.out.println(e.getEmpName());
Query query = session.createQuery("delete Employee where empId=6");
query.executeUpdate();
System.out.println(e.getEmpName());
session.getTransaction().commit();
*/
//inner join 内连接;这里用到了like的模糊查询
/*String hql = "from Department d join d.emp where d.depName like:likename";
Query query = session.createQuery(hql).setString("likename", "%软件%");
List list = query.list();
for(int i=0;i<list.size();i++){
Object[] obj = (Object[]) list.get(i);
Department dep = (Department) obj[0];
Employee emp = (Employee) obj[1];
System.out.println(dep.getDepName());
System.out.println("|---"+emp.getEmpName());
}
*/
//left join 左连接
/*String hql = "from Employee e join e.dep";
Query query = session.createQuery(hql);
List list = query.list();
for(int i=0;i<list.size();i++){
Object[] obj = (Object[]) list.get(i);
Department dep = (Department) obj[1];
Employee emp = (Employee) obj[0];
System.out.println(dep.getDepName());
System.out.println("|---"+emp.getEmpName());
}*/
//fetch 抓取;
String hql = "from Department d join fetch d.emp";
Query query = session.createQuery(hql);
//这里用list集合会重复抓取,这时可以用set集合;但是用set不能保证表里的顺序了就
List<Department> list = query.list();
Set<Department> set = new HashSet<Department>(list);
for(Department d : set){
System.out.println(d.getDepName());
for(Employee e: d.getEmp()){
System.out.println("|---"+e.getEmpName());
}
}
//简单连接,多表连接的时候,内连接,左右连接、抓取表中的空部门(没有对应雇员)都不显示出来,为了测试这个的原因
/*Query query = session.createQuery("from Department");
List<Department> list = query.list();
for(Department d : list){
System.out.println(d.getDepName());
}*/
//测试分页
/*List<Employee> list = findEmployee(2,2);
for(Employee e : list){
System.out.println(e.getEmpName());
}
HibernateSessionFactory.closeSession();*/
}
//分页
public List<Employee> findEmployee(int nowPage,int pageSize){
Session session = HibernateSessionFactory.getSession();
session.beginTransaction();
Query query = session.createQuery("from Employee");
query.setFirstResult((nowPage-1)*pageSize);
query.setMaxResults(pageSize);
List<Employee> list = query.list();
session.getTransaction().commit();
HibernateSessionFactory.closeSession();
return list;
}
}