RSS
热门关键字:
当前位置 : 主页>编程开发>java编程>入门>列表

另类查询 Hibernate HQL 深度历险

来源:我要研发网 作者: 时间:1970-01-01 点击:



  传统SQL语言采用是结构化查询方法,而这种方法对于查询以对象形式存在数据却无能为力。幸运是,Hibernate为我们提供了一种语法类似于SQL语言,Hibernate查询语言(HQL),和SQL不同是,HQL是一种面向对象查询语言,它可以查询以对象形式存在数据。因此,本文就HQL如何工作以及如何使用HQL展开了深入讨论。 字串9

  SQL本身是非常强大。当SQL这种强大和处理面向对象数据能力相结合时,就产生了HQL。和SQL一样,HQL提供了丰富查询功能,如投影查询、聚合函数、分组和约束。任何复杂SQL都可以映射成HQL。

字串4

  本文第一部分将讨论HQL简单用法。第二部分将讨论在HQL中如何根据上下文关系进行查询。在第三部分将以一个例子来说明如何在实际应用中使用HQL。

字串1

  进入HQL世界 字串3

  一个ORM框架是建立在面向对象基础上。最例子是Hibernate如何提供类SQL查询。虽然HQL语法类似于SQL,但实际上它查询目标是对象。HQL拥有面向对象语言所有特性,这其中包括多态、继承和组合。这就相当于一个面向对象SQL,为了提供更强大功能,HQL还提供了很多查询函数。这些函数可以被分为四类:

字串6

  1. 投影函数 字串6

  2. 约束函数 字串2

  3. 聚合函数 字串2

  4. 分组函数

字串1

  使用HQL可以建立简单查询,也可以建立更复杂查询。在本文中并不讨论那些非常复杂查询,如含有子查询和很多连接查询。本文只讨论连接两个表查询。现在让我们开始接近HQL吧!

字串8

  投影 字串1

  如谓投影,就是一个可以访问对象或对象属性。在HQL中,可以使用from和select子句来完成这个工作。

字串4

  from子句返回指定所有实例。如from Order将返回Order类所有实例。换句话说,以上查询相当于以下SQL语句: 字串8

select * from order

  from 是最简单查询子句。from后面可以跟一个或多个类名(类名也可以带有别名)。为了得到Order和Product所有实例,可以使用如下查询: 字串6

from Order, Product

  和类名一样,别名也可以在from后使用,如下代码如示:

字串5

from Order as o, Product p

  当查询很复杂时,加入别名可以减少语句长度。我们可以看看如下SQL语句:

字串8

select o.*, p.* from order o, product p where o.order_id = p.order_id

  我们可以很容易看出,上面查询是一对多关系。在HQL中相当于一个类中包含多个其它类实例。因此,以上SQL写成HQL就是:

字串2


字串8

from Order as o inner join o.products as product

  现在让我们考虑另外一个从表中得到指定属性情况。这就是最常用select子句。这在HQL中工作方式和SQL中一样。而在HQL中,如果只是想得到类属性话,select语句是最后选择。以上SQL可以使用select子句改成如下HQL语句:

字串2

select product from Order as o inner join o.products as product

  以上HQL语句将返回Order中所有Products实例。如果要得到对象某一个属性,可以将HQL语句写成如下形式: 字串1

select product.name from Order as o inner join o.products as product

  如果要得到多个对象属性,可以将HQL语句写成如下形式:

字串6

select o.id, product.name from Order as o inner join o.products as product

  接下来,我们将进入下一个议题。假设我们需要根据某些条件得到数据。那么以上所述HQL语句将无法满足需求。为了达到这一目,我们就要用到下面将要讨论约束子句。 字串6

  约束 字串8

  从以上可知,投影返回是所有数据。但在大多数时候我们并不需要这么多数据。这就需要对数据进行过滤。在HQL中过滤数据子句和SQL一样,也是where。它语法类似于SQL,通过where子句,可以对行进行过滤。我们可以看看下面SQL语句: 字串4

  select * from orders where id = ‘1234’

  这条查询语句返回了id等于1234所有字段。和这条SQL对等是下面HQL语句: 字串6

select o from Order o where o.id=’1234’

  从以上两条语句可以看出,它们where子句非常相似。而它们唯一不同是SQL操作是记录,而HQL操作是对象。在HQL中,除了where子句可以过滤数据外,having子句也可以做到这一点(关于having子句详细内容我将在分组部分讨论)。投影和约束是两个基本操作,这两个操作再加上聚合函数话,那HQL将变得更加强大。下面我们就来讨论什么是聚合。 字串5

  聚合 字串7

  上述查询都是将每一个记录(对象)当做一个单位,而如果使用聚合,可以将一类记录(对象)当做一个单位。然后再对每一类记录(对象)进行一系列地操作,如对某一列取平均值、求和、统计行数等等。HQL支持以下聚合函数: 字串6

  1. avg(…), sum(…)

字串9

  2. min(…), max(…) 字串6

  3. count(*), count(…), count(distinct…), count(all…) 字串7


字串6

  以上聚合函数都返回数值类型。这些操作都可以在select子句中使用,如下所示: 字串7

select max(o.priceTotal) max(p.price) from Order o join o.products p group by o.id

  以上HQL语句返回了两个值和:orders表中priceTotal最大值和products表中price最大值之和。我们还可以使用having子句对分组进行过滤。如我们想按id统计priceTotal小于1000数量可按如下HQL语句去实现: 字串7

select count(o) from Order o having o.priceTotal < 1000 group by o.id

  我们还可以将聚合函数和having子句一起使用。如我们要按products表id统计price小于amount平均数产品数量,HQL语句如下: 字串8

select count(p) from Product p having p.price < avg(amount) group by p.id

  从上面一系列HQL语句可以看出,所有通过SQL实现,都可以通过HQL来实现。

字串8

  分组 字串2

  在上一部分,已经涉及到了分组概念。分组操作是行集合。它根据某一列(属性)对记录集进行分组。这一切是通过group子句实现。如下例子描述了group子句一般用法。 字串7

select count(o) from Order o having o.priceTotal >= 1200 and o.priceTotal <= 3200 group by o.id

  HQL中分组和SQL中分组类似。总之,除了一些对SQL特殊扩展外,其它所有SQL功能都可以使用HQL描述。在接下来部分,让我们举例说明如何在java中使用HQL。 字串8

  在java中使用HQL 字串3

  到现在为止,我们已经学习了HQL基本用法。接下来我们举一个例子来说明如何在Java中使用HQL。下面例子只给出了主要部分,由于本文只是讨论HQL用法,因此,关于Hibernate一些设置和在main()函数中调用Hibernate部分并未给出,读者可以参考相关文当。现在让我们看看下面例子。 字串3

  下面是必须引用

字串6

import java.util.List;
import org.hibernate.*;
import org.hibernate.cfg.*
import com.Order;

  下面是类声明 字串7

public class MyOrder
{
… …
}

  下面让我们来实现MyOrder类构造函数

字串3

public class MyOrder
{
SessionFactory sf;
public MyOrder()
{
Configuration cfg = new Configuration().addClass(Order.class);
sf = cfg.buildSessionFactory();
}
… …
}

  下面getOrder函数根据priceTotal区间值返回Order对象。 字串8


字串8

public class MyOrder
{
…. ….
public Order getOrder(String lower, String upper)
{
// 打开一个会话
Session sess = sf.openSession();
// HQL语句
String query = "select o from o "
"Order as o join o.products as p "
"where o.priceTotal > :priceTotalLower"
"and o.priceTotal< :priceTotalUpper";
Query q = sess.createQuery(query);
// 将两个参数传入HQL中
q.setDouble("priceTotalLower", Double.parseDouble(lower));
q.setDouble("priceTotalUpper", Double.parseDouble(upper));
List list = q.list();
Order o=(Order)list.iterator.next();
return o;
}
… …
}

  下面main函数将测试MyOrder类

字串1

public class MyOrder
{
… …
public static void main(String args[])
{
Order o=MyOrder().getOrder(“100”, “300”);
System.out.println(“id=” o.id);
… …
}
}

  小结

字串2

  上述代码演示了如何在Java中使用HQL,但HQL还有两点需要注意一下: 字串1

  1. HQL并不区分字母大小写,但在HQL中Java类和属性名必须和实际类和属性名一致。如SELECT和select之间可以互换,但Order和order却代表不同含义。 字串3

  2. 如果HQL中引用类未被导入,在HQL中必须引用具体包。如本例中,如果com.Order未被导入,在HQL中必须将Order写成com.Order。

字串8

字串7

最新评论共有 0 位网友发表了评论
发表评论
评论内容:不能超过250字,需审核,请自觉遵守互联网相关政策法规。
用户名: 密码:
匿名?
注册
相关文章