zoukankan      html  css  js  c++  java
  • hibernate -- HQL语句总结

    本章介绍了Hibernate的几种主要检索方式:HQL检索方式、QBC检索方式、SQL检索方式。HQLHibernate Query Language的缩写,是官方推荐的查询语言。QBCQuery By Criteria的缩写,是Hibernate提供的一个查询接口。Hibernate是一个轻量级的框架,它允许使用原始SQL语句查询数据库。

    1.1 HQL基础

    HQLHiberante官方推荐的Hibernate检索方式,它使用类似SQL的查询语言,以面向对象的方式从数据库中查询。可以使用HQL查询具有继承、多态和关联关系的数据。在检索数据时应优先考虑使用HQL方式。

    1.1.1 默认数据库表和数据

    在讲解本章时,在没有特殊说明时,用到的数据库均为joblog,也就是在第4章建立的数据库。joblog中添加了3个表:学生表student、课程表course和选课表sc

    学生表student中各字段的结构如图6-1所示,字段的中文含义在Comment列中。

    Hibernate <wbr>中HQL语句(一)

    6-1 学生表的数据结构

    学生表student中的数据如图6-2所示,没有特殊说明时,用到的均为这6条记录。

    此处仍然使用在第4章建立的HibernateProject项目,但是这里新建了一个包hibernate.ch06,这个包存放本章中的所有代码。在hibernate.ch06包中建立学生表对应的持久化类Student.java,代码如下。

    Hibernate <wbr>中HQL语句(一)

    6-2 学生表中的数据

    package hibernate.ch06;

    // 学生类

    public class Student {

        private Integer id; // 对象标识符

        private Integer sno;// 学号

        private String sname; // 姓名

        private String ssex;// 性别

        private String sdept; // 所在系别

        private Integer sage; // 年龄

        private String saddress; // 籍贯

        …… //省略了所有的get/set访问器

    }

    课程表course中的各个字段的结构如图6-3所示,字段的中文含义在Comment列中。

    Hibernate <wbr>中HQL语句(一)

    6-3 课程表的结构

    课程表中的数据如图6-4所示,如果没有特殊说明,用到的均为这4条记录。

    Hibernate <wbr>中HQL语句(一)

    6-4 课程表的数据

    hibernate.ch06中新建持久化类Course.java类,代码如下。

    package hibernate.ch06;

    // 课程类

    public class Course {

        private Integer id; // 对象标识符

        private Integer cno;// 课程号

        private String cname; // 课程名

        private Integer Ccredit; // 学分

        …… //省略了get/set访问器

    }

    选修表scscstudent-course的缩写)的结构如图6-5所示,字段的中文含义在Comment列中。

    Hibernate <wbr>中HQL语句(一)

    6-5 选修表的结构

    选修表中的数据如图6-6所示,没有特殊说明时,用到的均为这5条记录。

    Hibernate <wbr>中HQL语句(一)

    6-6 选修表的数据

    hibernate.ch06中新建持久化类SC.javaSC.java的代码如下。

    package hibernate.ch06;

    // 选课类

    public class SC implements java.io.Serializable {

        private Integer id; // id

        private Integer sno; // 学号

        private Integer cno; // 课程号

        private Integer grade; // 成绩

        public SC() {

        }

        …… // 省略get/set访问器

    }

    后面的章节中将用这3个表和3个持久化类进行讲解。

    1.1.2 检索类的所有对象

    使用HQL语句可以检索出一个类的所有对象,如HQL语句“from Student”表示检索Student类的所有对象。下面的程序检索学生类的所有对象。

        Query query = session.createQuery("from Student"); // 创建Query对象

        List list = query.list(); // 执行查询

        

        // 以下代码做显示用,以后不再写出来

        Iterator it = list.iterator();

        while (it.hasNext()) {

            Student stu = (Student) it.next();

            System.out.println("id" + stu.getId());

            System.out.println("name" + stu.getSname());

            System.out.println(" ");

    }

    Hibernate <wbr>中HQL语句(一)     session.createQuery()HQL查询语句为参数,生成一个查询对象。本例中的HQL语句为“from Student”,这是from子句,格式如下。

    from 类名

    其中,类名可以为类的全限定名,如:

    from hibernate.ch06.Student

    Hibernate使用自动引入功能(auto import),会自动寻找需要的类,所以不推荐使用类的全限定名。注意,类名区分大小写,如果写成from student,将会抛出以下异常。

    java.lang.NoClassDefFoundError: hibernate/ch06/student (wrong name: hibernate/ch06/Student)

    Hibernate <wbr>中HQL语句(一)     HQL关键字不区分大小写,FROMfromFrom是一样的

    调用query.list()时,真正开始执行HQL查询语句,并把查询的结果放在List中。

    本例中查询的是Student类中的所有属性,如果查询Student类中的某一个或某几个属性,如查询所有学生的姓名和所在系,需要用到属性查询。

    1.1.3 检索类的某几个属性

    SQL语句类似,HQL语句可以检索类的某一个或者某几个属性。以下代码查询所有学生的姓名和所在系。

        // 创建Query对象

        Query query = session.createQuery("select Student.sname,Student.sdept from Student");

        List list = query.list(); // 执行查询

        // 以下代码显示查询的信息

        Iterator it = list.iterator();

        while (it.hasNext()) {

            Object[] stu = (Object[]) it.next();

            System.out.println("id" + stu[0]);

            System.out.println("name" + stu[1]);

            System.out.println(" ");

    }

    Hibernate <wbr>中HQL语句(一)     属性查询使用select关键字,属性查询的格式如下。

    select 属性1,属性2,… from 类名

    Hibernate <wbr>中HQL语句(一)     属性前可以加上类名加以限定,如:

    select 属性1,属性2,… from 类名

    但一般没有必要。

    属性查询区分大小写,上面的代码中如果写成:

    select SNAME,Sdept from Student

    将抛出异常,提示找不到属性SNAME和属性Sdept

    Hibernate <wbr>中HQL语句(一)     查询结果将只显示查询的属性列。

    Hibernate <wbr>中HQL语句(一)     属性查询的结果,对于用it.next()获得的每条记录,可以存储在Object[]数组中,以便进行存取。

    1.1.4 指定别名

    在查询时,可以用关键字as指定查询的别名,指定别名可以简化查询,有时必需指定别名才能进行查询。以下代码查询学号中含有4的学生的姓名和所在系。

    select s.sname,s.sdept from Student as s where s.sno like '%4%'from Student s

    s就是类Student的别名。注意as可以省略,即下面的查询语句和上面的语句是等效的。

    select s.sname,s.sdept from Student s where s.sno like '%4%'from Student s

    1.1.5 where条件子句

    where条件子句跟SQL中的where条件子句类似,它检索符合条件的对象。例如,查询所有所在系别为计算机系的学生:

    select s.sname,s.sdept from Student s where s.dept=’计算机

    Hibernate <wbr>中HQL语句(一)     where子句指定查询的条件,其语法和SQL类似。

    Hibernate <wbr>中HQL语句(一)     在where子句中可以指定比较运算符:>>=<<=<>,其含义分别为大于、大于等于、小于、小于等于、不等于

    查询年龄在2223岁的学生:

    from Student s where s.sage>=22 and s.sage<=23

    Hibernate <wbr>中HQL语句(一)     where子句中指定查询的属性是否为nullis nullis not null,其含义分别表示为空和不为空。

    查询所在籍贯为空的学生:

    from Student s where s.saddress is null

    1.1.6 使用distinct过滤掉重复值

    使用distinct关键字将去掉结果中的重复值,只检索符合条件的对象。如下面的例子检索学生实例中的不重复的年龄。

            Session session=Hsf.currentSession();//创建Session

            String hql="select distinct s.sage from Student s";       //HQL查询语句

            Query query=session.createQuery(hql);//创建查询

            List list=query.list();    //执行查询

    检索的结果如下,可见结果中去掉了一个重复的22岁。

    20

    21

    22

    23

    24

    1.1.7 删除对象

    HQL语句可以直接对复合条件的对象进行删除,可以指定删除的对象,并在提交后永久持久化到数据库。HQL使用delete进行删除,如删除年龄大于25岁的学生可以使用如下代码。

            Session session=Hsf.currentSession();        //创建Session

            Transaction tx=null;       //声明事务

            

            try{

       tx=session.beginTransaction();  //开始事务

               

      //创建查询

       String hql="delete Student s where s.sage>25";

       Query query=session.createQuery(hql);

       query.executeUpdate();           //执行

     tx.commit();           //成功,则提交

       tx=null;

            }catch(Exception e){

       e.printStackTrace();

       if(tx!=null){

      tx.rollback();    //失败则回滚

           

        }

            }finally{

       session.close();

            }

    注意以下两点。

    Hibernate <wbr>中HQL语句(一)     在删除对象时,执行query.executeUpdate()进行数据删除,但只有执行了tx.commit()进行事务提交时,才真正从数据库中删除数据。

    Hibernate <wbr>中HQL语句(一)     如果设置了级联删除,则与之相关联的对象实例也被删除。

    1.1.8 更新对象值

    更新对象的HQL语句与SQL语法很相似,使用update更新对象的值。如下面例子更新对象的sage属性。

            ransaction tx=null;         //声明事务

            try{

       tx=session.beginTransaction();  //开始事务

               

       String hql="update Student s set s.sage='22' where s.id=11";   //更新语句

       Query query=session.createQuery(hql);

       query.executeUpdate();           //执行

       tx.commit();           //成功,则提交

       tx=null;

            }catch(Exception e){

       e.printStackTrace();

       if(tx!=null){

               tx.rollback(); //失败则回滚

       }

            }finally{

       session.close();

            }

    1.1.9 查询计算属性值

    HQL可以查询经过计算的值,在一些需要计算的地方可以进行计算,例如查询全体学生的姓名和出生年份。

    select s.sname,2006-s.sage from Student as s

    Hibernate <wbr>中HQL语句(一)     select子句十分灵活,几乎和SQL语句有着同样的能力,对象的属性值可以参与运算。

    Hibernate <wbr>中HQL语句(一)     这行代码假设当前的年份是2006年。

    下面是另外几个查询计算属性值的例子。

    select s.sname,2006-s.sage from Student as s

    1.1.10 使用函数

    当需要调用函数时,HQL提供了一些类似SQL的函数。这些函数可以简化操作。例如查询学生的姓名、出生日期和性别,其中性别用小写表示。

    select s.sname,2006-s.sage,lower(s.ssex) from Student as sselect s.sname,2006-s. sage from Student as s

    1.1.11 between...and...not between... and...确定查询范围

    between...and...用来查询属性值在指定范围内的实体对象,not between...and...用来查询属性值不在指定范围内的实体对象。如查询学生年龄在2223之间的学生:

    select s.sno,s.sname,s.sage from Student s where s.sage between 22 and 23

    查询将返回如下结果。

    ---------------------------------------------------------------------

    1    20040001 李晓梅    22    计算机系   

    ---------------------------------------------------------------------

    2    20040002 王蒙       23    外语系   

    ---------------------------------------------------------------------

    4    20050004 李文       22    计算机系   

    between后跟的是查询范围的下限,and后跟的是查询范围的上限,所以下面的查询语句总没有对象返回。

    from Student s where s.sage between 23 and 22

    1.1.12 innot in确定查询集合

    关键字in用来查询指定属性值属于指定集合的对象,关键字not in用来查询指定属性值不属于指定集合的对象。如查询不是计算机系,也不是数学系的学生。

    select s.sno,s.sname,s.sdept from Student s where s.sdept not in ('计算机系','数学系')

    查询将返回如下结果。

    ---------------------------------------------------------------------

    20040002         王蒙         外语系   

    ---------------------------------------------------------------------

    20050003         姜浩         化学系   

    ---------------------------------------------------------------------

    20050005         薛鹏         生物系   

    1.1.13 like进行模糊查询

    like进行模糊查询时有两个可用的通配符:“%”“_”“%”代表长度大于等于0的字符,“_”代表长度为1的单个字符

    查询姓李的学生:

    select s.sno,s.sname,s.sdept from Student s where s.sname like '%%'

    查询结果如下。

    ---------------------------------------------------------------------

    20040001         李晓梅    计算机系   

    ---------------------------------------------------------------------

    20050004         李文       计算机系   

    ---------------------------------------------------------------------

    20050006         李思       数学系   

    查询姓名为两个字符的学生:

    select s.sno,s.sname,s.sdept from Student s where s.sname like '__'

    查询结果如下。

    ---------------------------------------------------------------------

    20040002    王蒙    外语系   

    ---------------------------------------------------------------------

    20050003    姜浩    化学系   

    ---------------------------------------------------------------------

    20050004    李文    计算机系   

    ---------------------------------------------------------------------

    20050005    薛鹏    生物系   

    ---------------------------------------------------------------------

    20050006    李思    数学系   

    1.1.14 and逻辑与

    当要检索指定的多个条件,且条件的逻辑关系为与时,使用“and”关键字。如检索计算机系的女生,这个检索要求包含两个条件:计算机系女生

    select s.sno,s.sname,s.sdept from Student s where s.sdept='计算机系' and s.ssex='F'

    检索的结果如下。

    ---------------------------------------------------------------------

    20040001         李晓梅    计算机系   

    ---------------------------------------------------------------------

    20050004         李文      计算机系   

    1.1.15 or逻辑或

    当检索的多个条件,且条件的逻辑关系为或时,使用“or”关键字。如检索姓王,或者年龄大于22岁的学生:

    select s.sno,s.sname,s.sdept from Student s where s.sname like '%' or s.sage>22

    检索结果如下。

    ---------------------------------------------------------------------

    20040002         王蒙         外语系   

    ---------------------------------------------------------------------

    20050005         薛鹏         生物系

    1.1.16 order by对结果进行排序

    “order by”关键字对结果进行排序,默认为升序。“order by asc”为升序,“order by desc”为降序。例如将学生表中的学生按照年龄升序排序:

    from Student s order by s.sage

    检索结果如下。

    ---------------------------------------------------------------------

    6    20050006         李思         20         数学系   

    ---------------------------------------------------------------------

    3    20050003         姜浩         21         化学系   

    ---------------------------------------------------------------------

    1    20040001         李晓梅      22        计算机系   

    ---------------------------------------------------------------------

    4    20050004         李文         22         计算机系   

    ---------------------------------------------------------------------

    2    20040002         王蒙         23         外语系   

    ---------------------------------------------------------------------

    5    20050005         薛鹏         24         生物系   

    将学生表中的学生按照年龄降序排列,按照所在系升序排列。

    from Student s order by s.sage,s.sdept desc

    1.1.17 group by对记录进行分组

    对查询进行分组可以对查询进行细化。分组经常和聚集函数一起使用,这样聚集函数将作用于每个分组。

    Hibernate <wbr>中HQL语句(一)     group by的用法为:

    select 属性1,属性2,属性,属性n from 类名 group by 属性m

    Hibernate <wbr>中HQL语句(一)     其中属性1,属性2,属性n必须满足下列条件。

    要么作为聚集函数的参数,要么为属性m。例如,检索各个系的学生的平均年龄:

    select avg(s.sage),s.sdept from Student s group by s.sdept

    其中字段s.sage作为平均值函数的参数,s.sdeptgroup by后的一个属性。检索的结果如下。

    ---------------------------------------------------------------------

    化学系         21.0   

    ---------------------------------------------------------------------

    计算机系       22.0   

    ---------------------------------------------------------------------

    生物系         24.0   

    ---------------------------------------------------------------------

    数学系         20.0   

    ---------------------------------------------------------------------

    外语系         23.0   

    检索各个课程号与对应的选课人数。

    select cno,count(sno) from SC s group by s.cno

    1.1.18 having关键字

    having关键字和group by关键字搭配使用,它对分组后的记录进行筛选,输出符合having指定条件的组。例如查询人数超过1000人的系。

    select s.sdept from Student s group by s.sdept having count(*)>1000

    查询男生人数多于500人的系。

    select s.sdept from Student s where s.ssex=’M’ group by s.sdept having count(*)>500

    Hibernate <wbr>中HQL语句(一)     以上面查询男生人数多于500人的系为例:

    select s.sdept from Student s where s.ssex=’M’ group by s.sdept having count(*)>500

    查询过程中同时使用group byhaving关键字时,查询步骤如下。

    1)检索符合s.ssex=‘M’的所有男生。

    2)根据s.sdept分组成不同的系。

    3)对于每一个分组,计算分组中的记录条数大于500的系。

    4)将符合上述条件的s.sdept选出来。

    Hibernate <wbr>中HQL语句(一)     wherehaving的区别在于作用对象不同。where作用于基本表,而having作用于分组后的组。

    1.1.19 聚集函数

    聚集函数包括count()avg()sum()max()min(),其含义如表6-1所示。

    6-1         聚集函数及其含义

    聚 集 函 数

        

    count()

    计算符合条件的记录条数

    avg()

    计算符合条件的平均值

    sum()

    计算符合条件的和

    max()

    计算符合条件的最大值

    min()

    计算符合条件的最小值

    Hibernate <wbr>中HQL语句(一)     各个函数的用法举例如下。

    检索学生实例的对象个数:

    select count(*) from Student

    检索计算机系的人数:

    select count(*) from Student s where s.sdept='计算机系'

    检索学生实例的平均年龄:

    select avg(s.sage) from Student s

    检索课程表course的所有课程的学分的总和:

    select sum(c.ccredit) from Course c

    检索课程号为“1”的课程的最高成绩:

    select max(s.grade) from SC s where s.cno=1

    检索课程号为“1”的课程的最低成绩:

    select min(s.grade) from SC s where s.cno=1

    Hibernate <wbr>中HQL语句(一)     聚集函数经常和group by分组关键字搭配使用。

    检索各门课程的平均成绩:

    select s.cno,avg(s.grade) from SC s group by s.cno

    检索各科不及格人数:

    select s.cno,count(*) from SC s where s.grade<60 group by s.cno

    1. 查询整个映射对象所有字段

    //直接from查询出来的是一个映射对象,即:查询整个映射对象所有字段  
            String hql = "from Users";  
            Query query = session.createQuery(hql);  
                
            List<Users> users = query.list();  
            for(Users user : users){  
                System.out.println(user.getName() + " : " + user.getPasswd() + " : " + user.getId());  
            }  
       
     输出结果为:  
    name1 : password1 : 1 
    name2 : password2 : 2 
    name3 : password3 : 3 

    2.查询字段  

    //查询其中几个字段  
            String hql = " select name,passwd from Users";  
            Query query = session.createQuery(hql);  
            //默认查询出来的list里存放的是一个Object数组  
            List<Object[]> list = query.list();  
            for(Object[] object : list){  
                String name = (String)object[0];  
                String passwd = (String)object[1];  
                    
                System.out.println(name + " : " + passwd);  
            }  
    输出结果为:  
    name1 : password1  
    name2 : password2  
    name3 : password3 

    3.修改默认查询结果(query.list())不以Object[]数组形式返回,以List形式返回

    //查询其中几个字段,添加new list(),注意list里的l是小写的。也不需要导入包,这样通过query.list()出来的list里存放的不再是默认的Object数组了,而是List集合了 
             String hql = " select new list(name,passwd) from Users";  
            Query query = session.createQuery(hql);  
            //默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是List集合了  
            List<List> list = query.list();  
            for(List user : list){  
                String name = (String)user.get(0);  
                String passwd = (String)user.get(1);  
                    
                System.out.println(name + " : " + passwd);  
            }  
            /** 
            输出结果为: 
             name1 : password1 
            name2 : password2 
            name3 : password3 
             */ 

    4.修改默认查询结果(query.list())不以Object[]数组形式返回,以Map形式返回

    //查询其中几个字段,添加new map(),注意map里的m是小写的。也不需要导入包,这样通过query.list()出来的list里存放的不再是默认的Object数组了,而是map集合了  
            String hql = " select new map(name,passwd) from Users";  
            Query query = session.createQuery(hql);  
            //默认查询出来的list里存放的是一个Object数组,但是在这里list里存放的不再是默认的Object数组了,而是Map集合了  
            List<Map> list = query.list();  
            for(Map user : list){  
                //一条记录里所有的字段值都是map里的一个元素,key是字符串0,1,2,3....,value是字段值  
                //如果将hql改为:String hql = " select new map(name as username,passwd as password) from Users";,那么key将不是字符串0,1,2...了,而是"username","password"了  
                String name = (String)user.get("0");//get("0");是get(key),注意:0,1,2...是字符串,而不是整形  
                String passwd = (String)user.get("1");  
                    
                System.out.println(name + " : " + passwd);  
            }  
            /** 
            输出结果为: 
             name1 : password1 
            name2 : password2 
            name3 : password3 
             */ 

    5.修改默认查询结果(query.list())不以Object[]数组形式返回,以自定义类型返回

    6.条件查询

    //条件查询,参数索引值从0开始,索引位置。通过setString,setParameter设置参数  
            String hql = "from Users where name=? and passwd=?";  
            Query query = session.createQuery(hql);  
            //第1种方式  
    //      query.setString(0, "name1");  
    //      query.setString(1, "password1");  
            //第2种方式  
            query.setParameter(0, "name1",Hibernate.STRING);  
            query.setParameter(1, "password1",Hibernate.STRING);  
            List<Users> list = query.list();  
            for(Users users : list){  
                System.out.println(users.getId());  
            }  
    //条件查询,自定义索引名(参数名):username,:password.通过setString,setParameter设置参数  
            String hql = "from Users where name=:username and passwd=:password";  
            Query query = session.createQuery(hql);  
            //第1种方式  
    //      query.setString("username", "name1");  
    //      query.setString("password", "password1");  
            //第2种方式,第3个参数确定类型  
            query.setParameter("username", "name1",Hibernate.STRING);  
            query.setParameter("password", "password1",Hibernate.STRING);  
            List<Users> list = query.list();  
            for(Users users : list){  
                System.out.println(users.getId());  
            

      

    //条件查询,通过setProperties设置参数  
            String hql = "from Users where name=:username and passwd=:password";  
            Query query = session.createQuery(hql);  
            //MyUser类的2个属性必须和:username和:password对应  
            MyUser myUser = new MyUser("name1","password1");  
            query.setProperties(myUser);  
            List<Users> list = query.list();  
            for(Users users : list){  
                System.out.println(users.getId());  
            

      

    7.update 数据

               执行SQL语句(为什么要用SQL语句,我想是为了执行某些复杂的SQL语句吧) 

    String sql="update Table set field = 'test'"
    Session session = HibernateSessionFactory.getSession();
    session.createSQLQuery(sql).executeUpdate();
    ts.commit();

         

       执行HQL语句   

    String hql="update Table set field = 'test'"
    Session session = HiberanteSessionFactory.getSession();
    Transaction ts = session.beginTransaction();
    Query query = session.createQuery(hql);
    query.executeUpdate();
    ts.commit();
  • 相关阅读:
    SOJ4478 Easy Problem II(模拟、栈)
    SOJ4480 Easy Problem IV (并查集)
    暴力枚举法总结
    区间DP学习总结
    51nod 1019 逆序数(逆序数+离散化)
    win7系统查看硬盘序列号步骤
    雷达图制作方法
    matlab更改打开时候默认路径
    excel多组数据散点图生成
    EndNote(三)之中文引文导入方式
  • 原文地址:https://www.cnblogs.com/jxldjsn/p/5369097.html
Copyright © 2011-2022 走看看