Criteria查询对查询条件进行了面向对象封装,符合编程人员的思维方式,不过HQL(Hibernate Query Language)查询提供了更加丰富的和灵活的查询特性,因此Hibernate将HQL查询方式立为官方推荐的标准查询方式,HQL查询在涵盖Criteria查询的所有功能的前提下,提供了类似标准SQL语句的查询方式,同时也提供了更加面向对象的封装。
这里以学生选课系统的表为例,讲解HQL。现提供三张表的SQL语句以及映射图。
--建立学生表 create table student ( sid number primary key , --学号 sname varchar2(45) not null, --学生姓名 ssex char(2) not null,--性别 sdept varchar2(10) not null, --所在系 sage number(3) ,--年龄 saddress varchar2(45) --住址 ); --学生表中的数据 insert into student values(20040001,'林青霞','F','计算机系',22,'上海'); insert into student values(20040002,'刘德华','M','外语系',23,'南京'); insert into student values(20050003,'成龙','M','化学系',21,'山东'); insert into student values(20050004,'林可欣','F','计算机系',22,'北京'); insert into student values(20050005,'周华健','M','生物系',24,'山东'); insert into student values(20050006,'周润发','M','数学系',20,'湖北'); --建立课程表 create table course ( cid number primary key ,--这是课程号 cname varchar2(50) not null,--课程名 ccredit number(3) --课程学分 ); insert into course values(11,'java编程',6); insert into course values(21,'c++课程',4); insert into course values(31,'oracle',3); insert into course values(41,'javaEE',100); insert into course values(51,'linux',1); --建立选课表 create table studCourse ( stuCourseId number primary key ,--这是一个自增的,表示一次选课 sid number references student(sid),--学生号 cid number references course(cid),--课程号 grade number not null--成绩 ); -- 建立选课序列 create sequence stucourse_seq start with 1 increment by 1 minvalue 1 nomaxvalue nocycle nocache ; --初始化数据 insert into studCourse values(stucourse_seq.nextval,20040001,11,90); insert into studCourse values(stucourse_seq.nextval,20040001,21,19); insert into studCourse values(stucourse_seq.nextval,20050003,21,45); insert into studCourse values(stucourse_seq.nextval,20050004,41,99); insert into studCourse values(stucourse_seq.nextval,20050006,11,39);
PS:在设计表的时候,应当每张表都有一个主键,且该主键最好不含业务逻辑。
基本语法:
from Domain类名
案例:
from Student -- 查询Student表中所有数据
基本语法:
select 属性1,属性2 from Domain类名
案例:
select sname,sage from Student
基本语法:
session.createQuery(“from xxx where id=123456”).uniqueResult();
案例:
Student s=(Student) session.createQuery("from Student where sid = 20050003").uniqueResult();
PS:如果检索一个对象,明确知道最多只有一个对象,则建议使用该方法。
基本语法:
select distinct 属性1,属性2 from Domain类名
案例:
List list=session.createQuery("select distinct sage,ssex from Student").list(); for(int i=0;i<list.size();i++){ Object [] objs=(Object[]) list.get(i); System.out.println(objs[0].toString()+" "+objs[1].toString()); }
PS:通过使用distinct可以过滤掉重复的数据。
基本语法:
[select 属性列表] from Domain类名 where 属性名 between 数值下界 and 数值上界
案例:
List list=session.createQuery("select distinct sage,ssex,sname from Student where sage between 20 and 22").list(); for(int i=0;i<list.size();i++){ Object [] objs=(Object[]) list.get(i); System.out.println(objs[0].toString()+" "+objs[1].toString()+objs[2].toString()); }
基本语法:
[select 属性列表] from Domain类名 where 属性名 in[not in](‘条件1’,’条件2’,’条件3’)
案例:
List<Student> list=session.createQuery("from Student where sdept in ('计算机系','外语系')").list(); //取出 for 增强 for(Student s:list){ System.out.println(s.getSname()+" "+s.getSaddress()+" "+s.getSdept()); }
基本语法:
[select 属性列表] from Domain类名 where 属性名 like ‘字符串’
案例:
from Student where sname like ‘林%’
案例1:
//显示各个系的学生的平均年龄 List<Object[]> list=session.createQuery("select avg(sage),sdept from Student group by sdept").list(); //取出1. for 增强 for(Object[] obj:list){ System.out.println(obj[0].toString()+" "+obj[1].toString()); }
案例2:
//1.对分组查询后的结果,进行筛选:比如请显示人数大于3的系名称 //a. 查询各个系分别有多少学生. List<Object[]> list=session.createQuery("select count(*) as c1,sdept from Student group by sdept having count(*)>3").list(); //取出1. for 增强 for(Object[] obj:list){ System.out.println(obj[0].toString()+" "+obj[1].toString()); }
案例3:
//2查询女生少于200人的系 //a.查询各个系的女生有多个个 List<Object[]> list=session. createQuery("select count(*) as c1,sdept from Student where ssex='F' group by sdept").list(); //取出1. for 增强 for(Object[] obj:list){ System.out.println(obj[0].toString()+" "+obj[1].toString()); }
案例4:
//1.查询计算机系共多少人?->如果我们返回的是一列数据 //这时我们的取法是直接取出list->object 而不是 list->Object[] List<Object[]> list=session.createQuery("select sage from Student where sdept='计算机系'").list(); //取出1. for 增强 for(Object obj:list){ System.out.println(obj.toString()); }
案例5:
//3.查询选修11号课程的最高分和最低分. List<Object[]> list=session. createQuery("select 11,max(grade),min(grade) from Studcourse where course.cid=11").list(); //取出1. for 增强 for(Object[] obj:list){ System.out.println(obj[0].toString()+" max="+obj[1].toString()+" min="+obj[2].toString()); }
案例6:
//计算各个科目不及格的学生数量 List<Object[]> list=session.createQuery("select count(*),student.sdept from Studcourse where grade<60 group by student.sdept").list(); //取出1. for 增强 for(Object[] obj:list){ System.out.println(obj[0].toString()+" "+obj[1].toString()); }
PS:group by用于分组,having在分组后加限制条件,order by指定排序方式,聚集函数有count(),avg(),max(),min(),sum()五个,大部分内容和SQL中语法相似,给出以前相关内容的博客:Oracle表管理、Java数据库基础
public void showStuByPage(int pageSize,int pageNow){ Query q = session.createQuery(“from Student”); q.setFirstResult((pageNow - 1) * pageSize); //从第几条取 q.setMaxResult(pageSize); //取出几条 List list = q.list(); //执行 Iterator it=list.iterator(); //显示一下 while(it.hasnext){ Student s=(Student)it.next(); System.out.println(s.getSname()); System.out.println(s.getSage()); } String hql=“select count(*) from Student”; list=session.createQuery(hql).list(); int pageRow=((Integer)list.get(0)).intValue(); int pageCount=(pageRow+pageSize-1)/pageSize;//总页数 }
基本语法:
Query q = session.createQuery(from Domain类名 where 属性1=:参数1);
q.setParameter(“参数1”, ”值1”);
案例:
List<Student> list=session.createQuery("from Student where sdept=:a1 and sage >: sage").setString("a1", "计算机系").setString("sage", "2").list();
或者可以:
Query q = session.createQuery("from Student where sdept=:a1 and sage >: sage"); q.setString("a1", "计算机系"); q.setString("sage", "2");
基本语法:
Query q = session.createQuery(from Domain类名 where 属性1=?);
q.setParameter(“0”, ”值1”);
案例:
List<Student> list = session.createQuery("from Student where sdept=? and sage>?").setString(0, "计算机系").setString(1, "2").list();
或者是:
Query query=session.createQuery("from Student where sdept=? and sage>?"); query.setString(0, "计算机系"); query.setString(1, "2"); List <Student> list=query.list(); for(int i=0;i<list.size();i++){ Student s= list.get(i); System.out.println(s.getSname()+" "+s.getSage()); }
1.可读性好.
2.性能提高.
3.防止sql注入.
案例:
在: Student.hbm.xml 中
<query name="myquerytest"> <![CDATA[select sname,ssex from Student where sage>22]]> </query>
使用方法:
List list=session.getNamedQuery("myquerytest").list(); System.out.println(list.size()); Iterator it=list.iterator(); while(it.hasNext()){ Object obj[]=(Object[])it.next(); System.out.println("n="+obj[0]); }
PS:通过在映射文件中配置hql,可以使hql的查询更灵活。
案例:显示所有选择了21号课程的学生信息
from Student where sid in (select student.sid from StudCourse where course.cno='21')
案例:显示林青霞选择的所有课程名和成绩
select s1.sname,s2.course.cid,c1.cname,s2.grade from Student as s1,StudCourse as s2,Course as c1 where s1.sname='林青霞' and s1.sname=s2.student.sname and c1.cid=s2.course.cid
或者
select s1.course.cname,s1.grade from Studcourse s1 where s1.student.sname='林青霞'
案例:
//查询年龄大于10岁的学生 criteria Session s=HibernateUtil.getCurrentSession(); Transaction tx=s.beginTransaction(); Criteria cri=s.createCriteria(Student.class); //添加检索条件 cri.add(Restrictions.gt("sage", new Long(10))); List<Student> list=cri.list(); for(Student s1: list){ System.out.println(s1.getSname()); } tx.commit();
PS:Criteria的优点是更加面向对象,如果对hql语句不太了解的话可以使用。缺点是: 功能不如hql强大,而且hql是hibernate官方推荐使用的语句。
----------参考《韩顺平.hibernate从入门到精通》