zoukankan      html  css  js  c++  java
  • Hibernate五 HQL查询

    HQL查询
    一 介绍
    1.HQL:Hibernate Query Language,是一种完全面向对象的查询语言。
    使用Hibernate有多重查询方式可供选择:hibernate的HQL查询,也可以使用条件查询,甚至使用原生的SQL查询语句。Hibernate还提供了一种数据过滤功能,这些都用于删选目标数据。
    2.查询步骤:
    (1)获取Hibernate Session对象
    (2)编写HQL语句
    (3)以HQL语句为参数,调用Session的createQuery()方法创建查询对象
    (4)如果HQL语句包含参数,则调用Query的setXxx()方法为参数赋值
    (5)调用Query对象的list()或uniqueResult()方法返回查询结果列表
    例如:假设两个关联实体Person和MyEvent之间存在中N--N关联关系,具体的查询如下:
    private class HqlQuery{
    public static void main(String[] args) throws Exception{
    HqlQuery mgr=new HqlQuery();
    mgr.findPersons();
    }
    private void findPersons(){
    Session sess=HibernateUtil.currentSession();
    Transaction tx=sess.beginTransaction();
    //以HQL语句创建Query对象
    List p1=sess.creatQuery("select distinct p from Person p "+
    "join p.myEvents where title= :eventTitle")
    .setString("eventTitle","a simple title");
    .list();
    //遍历查询的全部结果
    for(Object ele:p1){
    Person p=(Person)ele;
    System.out.println(p.getName());
    }
    tx.commit();
    HibernateUtil.closeSession();
    }
    }
    注意:Query对象可以连续多次为HQL参数赋值,因为setXxx()方法返回的是Query本身,最后调用list()方法返回查询到的全部结果。Query还包含如下两个方法:
    setFirstResult(int firstResult):设置返回的结果集从第几条记录开始
    setMaxResult(int maxResults):设置本次查询返回的结果数目
    HQL语句本身不区分大小写,但是HQL语句中所使用的包名、类名、实例名、属性名都区分大小写
    二 具体使用
    1.from子句
    from Person 或者是 from Person as p
    as关键字是可选的,但是为了保留可读性,建议保留。
    from后还可以跟多个持久化类,此时将产生一个笛卡尔积或跨表的连接,但是这种做法并不经常使用,因为通常在做跨表的连接时,可以考虑使用隐式连接或显式连接,而不是在from后紧跟多个表名。
    2.关联和连接
    当程序需要从多个数据表中取得数据时,SQL语句会考虑使用多表连接查询。Hibernate使用关联映射处理底层数据表之间的连接,一旦提供了正确的关联映射后,当程序通过Hibernate进行持久化访问时,将可利用Hibernate的关联来进行连接。
    HQL支持两种关联连接(join):隐式和显式
    隐式连接不使用join关键字,使用英文点号.来隐式连接关联实体,如:from Person p where p.myEvents.title>:title
    显式连接需要使用xxx join关键字,如:from Person p inner join p.myEvents event where event.happenDate<:endDate
    主要有以下几种连接方式:
    inner join(内连接),简写为join
    left outer join(左外连接),简写为left join
    right outer join(右外连接),简写为right join
    full join(全连接),并不常用
    使用显式连接时,还可以通过with关键字提供额外的连接条件,如:
    from Person p inner join p.myEvents event with p.id>event.id where event.happenDate<:endDate
    隐式连接底层将转换成SQL99的交叉连接,显式连接底层将转换成SQL99的inner join,left join,right join等等。
    注意:隐式连接和显式连接查询后返回的结果不同
    在上述from Person p where p.myEvents.title>:title例子中,使用隐式连接查询返回的结果是多个被查询实体组成的集合,也就是Person对象组成的集合。
    而rom Person p inner join p.myEvents event with p.id>event.id where event.happenDate<:endDate例子中,使用显式连接查询返回的结果也是集合,但是集合元素是被查询的持久化对象、所有被关联的持久化对象所组成的数组。该例中同时选择了person和event表中的所有数据列,查询得到的结果集的每条记录既包含了Person实体的全部属性,也包含了MyEvent实体的全部属性。
    Hibernate3.2.2以前的版本中,会对所有的关联实体自动使用隐式连接,如:from Person p where p.myEvents.title =:eventTitle,但是在这以后,如果myEvents是一个集合,就会报错:QueryException,要改写为:
    from Person p inner join p.myEvents e where e.title =:eventTitle
    如果只想获取Person组成的集合,应改为:select p from Person p inner join p.myEvents e where e.title =:eventTitle,但是这么做会产生多个完全相同的Person对象,因此要改为:select distinct p from Person p inner join p.myEvents e where e.title =:eventTitle
    也就是说,对于Hibernate3.2.3以后的版本,如果关联实体是单个实体或单个的组件属性,就可以使用隐式连接;当关联实体是集合,则必须使用xxx join来显式连接关联实体或组件。
    3.select子句
    select子句用于选择指定的属性或直接选择某个实体,选择的属性必须是from后持久化类包含的属性,如:
    select p.name from Person as p
    如果select后由多个选项,那么每个集合元素就是选择出的多项组成的数组,如:
    select p.name, p from Person as p
    执行该HQL语句得到的集合元素就是类似于[String,Person]结构的数组
    也可以将选择出的属性存入一个List对象中,如:
    select new List(p.name, p.address) from Person as p
    也可以将选择出的属性直接封装成对象,如:
    select new ClassTest(p.name,p.address) from Person as p
    前提是ClassTest支持p.name,p.address的构造器
    也可以给选中的表达式命名别名,如:
    select p.name as personName from Person as p
    这种做法与new map使用更为普遍:
    select new map(p.name as personName) from Person p
    执行上面的HQL语句返回的结果是集合,该Map对象以personName为key,实际的值为value。
    4.多态查询
    from后面跟持久化类名,不仅会查询出该持久化类的全部实例,还会查询出该类的子类的全部实例,如:
    from Person as p
    该查询语句不仅会查询出Person的全部实例,还会查出其子类,如Teacher的全部实例。
    5.where子句
    where子句用来筛选选中的结果,缩小选择的范围。
    select Person where name like 'tom%'
    select Person as p where p.name like "tom%"
    以上两种写法的效果是一样的。
    只要没有集合属性,使用隐式连接多个数据库会相当方便,不会感受到多表连接查询的繁琐。
    6.表达式
    where子句后支持的运算符非常丰富,允许使用大部分SQL支持的表达式,包括:
    数学运算符:+ - * /等
    二进制比较运算符:= >= <= <> != like
    逻辑运算符:and or not 等
    in not in between is null is not null is emtpy is not empty等等
    字符串连接符: value1 || value2 concat(value1,value2)
    时间操作函数: current_date() current_time() current_timestamp() second() minute() hour() day() month() year()
    EJB-QL3.0所支持的函数或操作:substring() trim() lower() upper() length()等等
    where子句还支持以下的特殊关键字用法:
    (1)HQL index()函数:作用于join的有序集合的别名
    (2)HQL 函数,把集合作为参数:size(),minelement(),maxelement(),minindex(),maxindex()
    (3)in和between...and的用法:select DemesticCat cat where cat.name between 'A' and 'B'
    select DemesticCat cat where cat.name in ('Foo','Bar','Baz')
    当然,也支持not between和not in的用法
    (4)is null 和is not null用来测试空值
    (5)size关键字用来返回一个集合的大小
    from Cat cat where cat.kittens.size>0或者from Cat cat where size(cat.kittens)>0
    (6)对于有序集合,还可以使用minindex(),maxindex()函数代表最小与最大的索引序数,如:
    from Calendar cal where maxindex(order.items) >100
    7.order by子句
    查询返回的集合可以根据类或组件属性的任何属性进行排序,如:
    from Person as p order by p.name,p.age
    可以使用asc或desc关键字指定升序或降序的排序规则,如:
    from Person as p order by p.name asc,p.age desc
    8.group by子句
    返回聚集值的查询可以对持久化类或组件属性的属性进行分组,分组使用group by子句,如:
    select cat.color,sum(cat.weight),count(cat)
    from Cat cat
    group by cat.color
    注意:出现在select后的属性,要么出现在聚集函数中,要么出现在group by的属性列表中。
    having子句用于对分组进行过滤,如:
    select cat from Cat cat
    join cat.kittens kitten
    group by cat
    having avg(kitten.weight)>100
    order by count(kitten) asc,sum(kitten.weight) desc
    9.子查询
    如果底层数据库支持子查询,则可以在HQL语句中使用子查询,如:
    from Cat as fatcat
    where fatcat.weight>(select avg(cat.weight) from DomesticCat cat);

  • 相关阅读:
    CentOS 6.4 x64 zabbix 2.2.2 编译安装
    Monitorix 监控 安装配置
    CentOS 6.4 x64 Percona-Server-5.6.15 源码安装
    CentOS 6.4 x64 安装 配置 Redmine 2.4.1
    ActiviMQ的基本使用
    Java内存 模型理解
    线程池的两种创建方式及区别
    线程创建的三种方式及区别
    Spring cloud 之Ribbon(二)负载均衡原理
    Spring cloud 之Ribbon(一)基本使用
  • 原文地址:https://www.cnblogs.com/lyy-2016/p/5727680.html
Copyright © 2011-2022 走看看