科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道另类查询 Hibernate HQL 深度历险

另类查询 Hibernate HQL 深度历险

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

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

作者:李宁 来源:天极网 2007年9月6日

关键字:

  • 评论
  • 分享微博
  • 分享邮件

在本页阅读全文(共2页)

约束

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

select * from orders where id = ‘1234’

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

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

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

聚合

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

1.avg(…), sum(…)

2.min(…), max(…)

3.count(*), count(…), count(distinct…), count(all…)

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

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语句去实现:

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

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

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

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

分组

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

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。

在Java中使用HQL

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

下面是必须引用的包

import java.util.List;

import org.hibernate.*;

import org.hibernate.cfg.*

import com.Order;



下面是类的声明

public class MyOrder

{

… …

}

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

public class MyOrder

{

SessionFactory sf;

public MyOrder()

{

Configuration cfg = new Configuration().addClass(Order.class);

sf = cfg.buildSessionFactory();

}

… …

}

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

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类

public class MyOrder

{

… …

public static void main(String args[])

{

Order o=MyOrder().getOrder(“100”, “300”);

System.out.println(“id=”+ o.id);

… …

}

}

小结

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

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

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

查看本文来源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章