Hibernate对多表关联查询

断线的纸鸢 贡献于2013-04-27

作者 USER  创建于2010-08-26 14:00:00   修改者USER  修改于2010-08-26 14:02:00字数5938

文档摘要:Hibernate简介Hibernate是一个JDO工具。它的工作原理是通过文件(一般有两种:xml文件和properties文件)把值对象和数据库表之间建立起一个映射关系。这样,我们只需要通过操作这些值对象和Hibernate提供的一些基本类,就可以达到使用数据库的目的。例如,使用Hibernate的查询,可以直接返回包含某个值对象的列表(List),而不必向传统的JDBC访问方式一样把结果集的数据逐个装载到一个值对象中,为编码工作节约了大量的时间。
关键词:

Hibernate对多表关联查询  由于公司项目的需要,我对Hibernate对多表关联查询研究了一下,现总结如下,供朋友参考。   一、 Hibernate简介Hibernate是一个JDO工具。它的工作原理是通过文件(一般有两种:xml文件和properties文件)把值对象和数据库表之间建立起一个映射关系。这样,我们只需要通过操作这些值对象和Hibernate提供的一些基本类,就可以达到使用数据库的目的。例如,使用Hibernate的查询,可以直接返回包含某个值对象的列表(List),而不必向传统的JDBC访问方式一样把结果集的数据逐个装载到一个值对象中,为编码工作节约了大量的时间。Hibernate提供的HQL是一种类SQL语言,它和EJBQL一样都是提供对象化的数据库查询方式,但HQL在功能和使用方式上都非常接近于标准的SQL.   二、 Hibernate与JDBC的区别Hibernate与JDBC的主要区别如下:   1、 Hibernate是JDBC的轻量级的对象封装,它是一个独立的对象持久层框架,和App Server,和EJB没有什么必然的联系。Hibernate可以用在任何JDBC可以使用的场合,从某种意义上来说,Hibernate在任何场合下取代JDBC.   2、 Hibernate是一个和JDBC密切关联的框架,所以Hibernate的兼容性和JDBC驱动,和数据库都有一定的关系,但是和使用它的Java程序,和App Server没有任何关系,也不存在兼容性问题。   3、 Hibernate是做为JDBC的替代者出现的,不能用来直接和Entity Bean做对比。   三、 Hibernate 进行多表关联查询Hibernate对多个表进行查询时,查询结果是多个表的笛卡尔积,或者称为“交叉”连接。 例如:from Student, Book from Student as stu, Book as boo from Student stu, Book boo注意:让查询中的Student和Book均是表student和book对应的类名,它的名字一定要和类的名字相同,包括字母的大小写。别名应该服从首字母小写的规则是一个好习惯,这和Java对局部变量的命名规范是一致的。   下面列举一个完整的例子来说明Hibernate对多个表进行关联查询(其中粗体是我们要特别注意的地方,相应表tBookInfo和BookSelection的结构和其对应的hbm.xml、class文件就不一一列举了,有需要详细了解的朋友,请联系我): String sTest = "from tBookInfo book, BookSelection sel where book.id = sel.bookId"; Collection result = new ArrayList(); Transaction tx = null; try {  Session session = HibernateUtil.currentSession();  tx = session.beginTransaction();  Query query = session.createQuery(sql);  result = query.list();  tx.commit(); } catch (Exception e) {  throw e; } finally {  HibernateUtil.closeSession(); } ArrayList sList = (ArrayList) result; Iterator iterator1 = sList.iterator(); while (iterator1.hasNext()) {  Object[] o = (Object[]) iterator1.next();  tBookInfo bookInfo = (tBookInfo) o[0];  BookSelection bookSelect = (BookSelection) o[1];  System.out.println("BookInfo-Title: " + bookInfo.getTitle());  System.out.println("BookSelection-BookSelectionId: " + bookSelect.getId()); } 另类查询 Hibernate HQL 深度历险 传统的SQL语言采用的是结构化的查询方法,而这种方法对于查询以对象形式存在的数据却无能为力。幸运的是,Hibernate为我们提供了一种语法类似于SQL的语言,Hibernate查询语言(HQL),和SQL不同的是,HQL是一种面向对象的查询语言,它可以查询以对象形式存在的数据。因此,本文就HQL如何工作以及如何使用HQL展开了深入的讨论。   SQL本身是非常强大的。当SQL的这种强大和处理面向对象数据的能力相结合时,就产生了HQL。和SQL一样,HQL提供了丰富的查询功能,如投影查询、聚合函数、分组和约束。任何复杂的SQL都可以映射成HQL。   本文的第一部分将讨论HQL的简单用法。第二部分将讨论在HQL中如何根据上下文关系进行查询。在第三部分将以一个例子来说明如何在实际应用中使用HQL。   进入HQL世界   一个ORM框架是建立在面向对象的基础上的。最好的例子是Hibernate如何提供类SQL查询。虽然HQL的语法类似于SQL,但实际上它的查询目标是对象。HQL拥有面向对象语言的所有的特性,这其中包括多态、继承和组合。这就相当于一个面向对象的SQL,为了提供更强大的功能,HQL还提供了很多的查询函数。这些函数可以被分为四类:   1. 投影函数   2. 约束函数   3. 聚合函数   4. 分组函数   使用HQL可以建立简单的查询,也可以建立更复杂的查询。在本文中并不讨论那些非常复杂的查询,如含有子查询和很多连接的查询。本文只讨论连接两个表的查询。现在让我们开始接近HQL吧!    投影   如谓投影,就是一个可以访问的对象或对象的属性。在HQL中,可以使用from和select子句来完成这个工作。   from子句返回指定的类的所有实例。如from Order将返回Order类的所有实例。换句话说,以上的查询相当于以下的SQL语句: select * from order   from 是最简单的查询子句。from后面可以跟一个或多个类名(类名也可以带有别名)。为了得到Order和Product的所有实例,可以使用如下的查询: from Order, Product   和类名一样,别名也可以在from后使用,如下代码如示: from Order as o, Product p   当查询很复杂时,加入别名可以减少语句的长度。我们可以看看如下的SQL语句: select o.*, p.* from order o, product p where o.order_id = p.order_id   我们可以很容易看出,上面的查询是一对多的关系。在HQL中相当于一个类中包含多个其它类的实例。因此,以上的SQL写成HQL就是: from Order as o inner join o.products as product   现在让我们考虑另外一个从表中得到指定属性的情况。这就是最常用的select子句。这在HQL中的工作方式和SQL中一样。而在HQL中,如果只是想得到类的属性的话,select语句是最后的选择。以上的SQL可以使用select子句改成如下的HQL语句: select product from Order as o inner join o.products as product   以上的HQL语句将返回Order中的所有Products实例。如果要得到对象的某一个属性,可以将HQL语句写成如下的形式: select product.name from Order as o inner join o.products as product   如果要得到多个对象的属性,可以将HQL语句写成如下形式: select o.id, product.name from Order as o inner join o.products as product   接下来,我们将进入下一个议题。假设我们需要根据某些条件得到数据。那么以上所述的HQL语句将无法满足需求。为了达到这一目的,我们就要用到下面将要讨论的约束子句。 约束   从以上可知,投影返回的是所有的数据。但在大多数时候我们并不需要这么多数据。这就需要对数据进行过滤。在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。

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 3 金币 [ 分享文档获得金币 ] 0 人已下载

下载文档