http://www.cnblogs.com/zilong882008/archive/2011/11/05/2237123.html
HQL是Hiberante官方推荐的Hibernate检索方式,它使用类似SQL的查询语言,以面向对象的方式从数据库中查询。可以使用HQL查询具有继承、多态和关联关系的数据。在检索数据时应优先考虑使用HQL方式。
本笔记将会沿用前面所使用的dept部门表,emp员工表。
dept部门表
emp员工表
1 查询实体
hibernate的session.createQuery()方法是使用HQL语句查询对象的。
hql:是查询对象的,例如:"from User",其中from不区分大小写,而User是区分大小写,因为它是对象。是User类
返回Query对象。
执行这条语句后,Hibernate会根据配置文件中所配置的数据库适配器自动生成相应数据库的SQL语句。
sql: select * from dept; from 后面是表名
hql: form Dept; from 后面是类。
可以对类起别名,有两种方法。
hql: from Dept d
hql:from Dept as d
以上两种起别名方法皆可。
public void Test1() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="from Dept"; //定义String类型hql,写入hql语句。 Query query=session.createQuery(hql); List<Dept> list = query.list(); for(Dept dept:list){ System.out.print("部门编号: "+dept.getDid() +" "); System.out.println("部门名称: "+dept.getDname()); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
执行结果
Hibernate: select dept0_.did as did1_, dept0_.dname as dname1_, dept0_.daddress as daddress1_ from dept dept0_
部门编号: 1 部门名称: 业务部
部门编号: 2 部门名称: 技术部
部门编号: 3 部门名称: 管理部
部门编号: 4 部门名称: 财务部
部门编号: 5 部门名称: 人力资源部
2 查询表中单个属性
sql: select ename from dept
hql: select ename from Dept
对属性也可以设置别名
hql:select ename as from Dept
as 必须加。
public void Test2() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); Query query=session.createQuery("select dname from Dept"); List<String> list = query.list(); for(String name:list){ System.out.println("部门名称: "+name); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
执行结果:
Hibernate: select dept0_.dname as col_0_0_ from dept dept0_
部门名称: 业务部
部门名称: 技术部
部门名称: 管理部
部门名称: 财务部
部门名称: 人力资源部
3 对多个属性进行查询
sql: select ename,eage from emp
hql:select ename,eage from Emp
hql: select e.ename,e.eage from Emp e
以上两种hql写法均可。
public void Test3() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); Query query=session.createQuery("select ename,eage from Emp"); List<Object[]> list = query.list(); //对多个属性查询的时候,使用Obejct数组。 for(Object[] message:list){ System.out.println(Arrays.toString(message)); //采用辅助类Arrays的toString()方法打印数组。 } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
测试结果
Hibernate: select emp0_.ename as col_0_0_, emp0_.eage as col_1_0_ from emp emp0_
[刘德华, 40]
[李世民, 34]
[曹操, 59]
[和珅, 44]
[贺龙, 45]
[郭富城, 34]
4 通过实体类方式查询多属性
除了上述方法外,还可以采用实体类的方式查询,要在Emp类中加入带有查询参数的构造器,代码如下。
public class Emp { private int eid; private int eage; private float esal; private String ename;
省略get,set方法。 public Emp() { super(); } public Emp(int eage, String ename) { //需要查询的属性是什么,构造器的参数就是什么。 super(); this.eage = eage; this.ename = ename; }
测试类
public void Test4() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); Query query=session.createQuery("select new Emp(eage,ename) from Emp e"); select 后直接调用构造器,参数就是查询的属性,参数不可错乱。 List<Emp> list = query.list(); 此处不实用object数组,类类型即可 for(Emp message:list){ System.out.print("姓名:"+message.getEname()+" "); System.out.println("年龄:"+message.getEage()); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
测试结果
Hibernate: select emp0_.eage as col_0_0_, emp0_.ename as col_1_0_ from emp emp0_
姓名:刘德华 年龄:40
姓名:李世民 年龄:34
姓名:曹操 年龄:59
姓名:和珅 年龄:44
姓名:贺龙 年龄:45
姓名:郭富城 年龄:34
本笔记继续使用dept部门表,emp员工表,一对多多对一双向映射。
1 条件查询
1.1 查询 员工表emp中 年龄eage小于30,月薪esal大于20000的员工姓名ename
sql:select ename from emp where eage<? and esal >?;
hql: select ename from Emp where eage<? and esal >?
1.2 问号的设置与别名
问号(?)的设置使用.setParameter(位置, 属性值) 在sql语句中问号的位置是从1开始,在hql中从零开始。
在hql中,问号(?)也可以起别用,:后面紧跟别名,setParameter("age", 30)方法也随之改变,将原先的数字改成"别名",如下所示
String hql="select ename from Emp where eage<:age and esal >:sal";
Query query= session.createQuery(hql).setParameter("age", 30).setParameter("sal", 20000f).list();
1.3 一组问号的设置
对于一组问号也可以设置别名:如 查询在1,2部门的员工姓名
hql="select ename from Emp where did in (?,?)";
hql="select ename from Emp where did in (:d)";
Query query= session.createQuery(hql).setParameter("d", new Object[]{1,2}).list();
public void Test9() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="select ename from Emp where eage<? and esal >?"; Query query= session.createQuery(hql).setParameter(0, 30).setParameter(1, 20000f); //设置问号,从0开始。 List<String> list = query.list(); for(String message:list){ System.out.println(message); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
结果:
Hibernate: select emp0_.ename as col_0_0_ from emp emp0_ where emp0_.eage<? and emp0_.esal>?
刘亦菲
白百何
文章
林月如
2 条件查询的常用关键字
2.1 distinct 过滤重复的值
查询员工表中的所有员工姓名,并去掉重复值
hql="select distinct ename from Emp ";
2.2 delete 删除
删除年龄大于25的员工
hql="delete Emp where eage>25"; 删除年龄大于25岁的用户
Query query=session.createQuery(hql);
query.executeUpdate(); //执行 executeUpdate 方法返回int类型。
tx.commit(); //成功,则提交,对数据库操作
2.3 update 更新
更新员工编号11的年龄为22
String hql="update Emp s set s.eage='22' where s.eid=11"; //更新语句
Query query=session.createQuery(hql);
query.executeUpdate(); //执行
tx.commit(); //成功,则提交
2.4 between...and...和not between... and...确定查询范围
查找员工表中年龄在20到30之间的员工姓名
hql="select ename from Emp where eage between 20 and 30"
2.5 in和not in确定查询集合
查询员工属于低1,2部门的员工姓名
hql="select ename from Emp where did in(1,2)"
2.6 like进行模糊查询
用like进行模糊查询时有两个可用的通配符:“%”和“_”。“%”代表长度大于等于0的字符,“_”代表长度为1的单个字符。
查询员工表中姓名中带有刘的员工
hql="select ename from Emp where ename like '%刘%'"
2.7 逻辑与 and 逻辑或 or
查询员工中薪水大于2000 同时年龄小于30的员工姓名
hql="select ename from Emp where esal>2000 and eage<30";
查询员工中,年龄大于40或者年龄小于30的员工
hql="select ename from Emp where eage>40 or eage<30";
2.8 order by对结果进行排序
对薪水进行排序,从小到大
hql="select esal from Emp where order by esal asc";
对年龄进行排序,倒叙,
hql="select ename from Emp where order by eage desc";
2.9 group by对记录进行分组
根据部门分组,求出各组的平均薪水
hql=" select avg(esal) from Emp group by did";
2.10 having 对分组进行筛选
根据部门分组,查出员工所在组平均薪水大于10000的员工姓名
hql=" select ename from Emp group by did having avg(esal)>10000";
3 聚集函数
查询emp员工表中有多少个员工。
sql:select count(ename) from emp;
hql: select count(ename) from Emp;
聚集函数及含义:
hql: select avg(esal) from Emp; 薪水平均值
hql: select max(esal) from Emp; 薪水最大值
hql: select sum(esal) from Emp; 薪水最小值
public void Test91() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="select count(ename) from Emp"; Object count=session.createQuery(hql).uniqueResult(); //uniqueResult()方法返回Object类型 System.out.println(count); tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
结果:
Hibernate: select count(emp0_.ename) as col_0_0_ from emp emp0_
15
4 子查询
Hibernate 支持子查询,所谓子查询就是,要查询的字段及信息在A表,条件在B表。语法与sql语句相似。
public void Test9() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="select ename from Emp where did in (select did from Dept where daddress = 302)"; Query query= session.createQuery(hql); List<String> list = query.list(); for(String message:list){ System.out.println(message); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
结果:
Hibernate: select emp0_.ename as col_0_0_ from emp emp0_ where did in (select dept1_.did from dept dept1_ where dept1_.daddress=302)
李世民
曹操
和珅
刘诗诗
5 导航查询
e.dept.daddress=301
员工所在部门的地址是301
public void Test9() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="select ename from Emp e where e.dept.daddress=301 "; Query query= session.createQuery(hql); List<String> list = query.list(); for(String message:list){ System.out.println(message); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
结果:
Hibernate: select emp0_.ename as col_0_0_ from emp emp0_, dept dept1_ where emp0_.did=dept1_.did and dept1_.daddress=301
刘德华
贺龙
白百何
文章
林月如
1 分页
setFirstResult(0),(从0开始)
setMaxResults(5),每页显示5条数据
public void Test1() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="select eage from Emp order by eage"; Query query= session.createQuery(hql).setFirstResult(0).setMaxResults(5); //从0开始,现实5条数据。 List<Integer> list = query.list(); for(Integer message:list){ System.out.println(message); } tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
Hibernate: select emp0_.eage as col_0_0_ from emp emp0_ order by emp0_.eage limit ?
21
21
24
24
24
2 表连接
Hibernate 支持内链接和外链接(左连接,右连接)
hql: from Emp e inner join fetch e.dept; 内链接
hql: from Emp e left join fetch e.dept; 左连接
hql:from Emp e right join fetch e.dept 右连接
public void Test2() throws Exception{ //实体 Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); Query query=session.createQuery("from Emp e inner join fetch e.dept where eage<30"); List<Emp> list = query.list(); for(Emp user:list){ System.out.println(user.getEname()); System.out.println(user.getDept().getDaddress()); tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
结果
Hibernate: select emp0_.eid as eid2_0_, dept1_.did as did1_1_, emp0_.ename as ename2_0_, emp0_.eage as eage2_0_, emp0_.esal as esal2_0_, emp0_.did as did2_0_, dept1_.dname as dname1_1_, dept1_.daddress as daddress1_1_ from emp emp0_ inner join dept dept1_ on emp0_.did=dept1_.did where eage<30
白百何
301
文章
301
林月如
301
刘诗诗
302
3 批量更新
将年龄在25岁一下的员工改成25岁
hql="update Emp e set e.eage=25 where e.eage<25";
删除25岁一下的员工
hql="delete Emp e where e.eage<25";
使用executeUpdate()方法必须启用事务。
public void Test3() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String hql="update Emp e set e.eage=25 where e.eage<25"; Query query=session.createQuery(hql); query.executeUpdate(); tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }
4 Hibernate 中使用SQL
HQL不是万能的,无法执行插入语句和非常复杂的查询,Hibernate 也支持SQL查询。通过连接直接调用cerateSQLQuery(sql)即可
sql语句中存在问号,同样使用setParameter(位置,属性值)方法设置。问号的位置从0开始,最后调用executeUpdate执行。事务提交后数据库开始工作。
public void Test4() throws Exception{ Configuration config=new Configuration().configure(); SessionFactory sessionFactory= config.buildSessionFactory(); Session session=null; Transaction tr=null; try{ session= sessionFactory.openSession(); tr=session.beginTransaction(); String sql="insert into emp (ename,eage) values (?,?)"; session.createSQLQuery(sql).setParameter(0, "曹雪芹").setParameter(1, 22).executeUpdate(); tr.commit(); }catch(Exception e){ tr.rollback(); }finally{ if(session!=null){ session.close(); } if(sessionFactory!=null){ sessionFactory.close(); } } }