`

在Hibernate中使用多表查询的一种实现

阅读更多
Hibernate是典型的OPM工具,它将每一个物理表格(Table)映射成为对象(Object),这发挥了面向对象的优势,使设计和开发人员可以从面向对象的角度来进行对数据库的管理。
    在设计到多表操作时,Hibernate提供了与数据库表关系相对应的对象映射关系,一对一、一对多和多对多在这里都可以通过Hibernate的对象映射关系(Set等)来实现。这为一般情况下的数据库多表操作提供了便捷途径。关于这方面的介绍已经很多,在这里不再复述。
    但是,在有些情况下的多表操作,比如一个统计顾客在2005年的消费总金额的SQL操作如下:
select b.name, count(a.fee) mix(a.chargeBeginTime) max(a.chargeEndTime) from charge a, customer b where a.idCustomer = b.idCustomer and a.chargeBeginTime >= '2005-01-01' and a.chargeEndTime < '2005-12-31' gourp by a.idCustomer
customer表和charge结构如下:

customer表结构:
+------------+-------------+------+-----+---------+-------+
| Field      | Type        | Null | Key | Default | Extra |
+------------+-------------+------+-----+---------+-------+
| IdCustomer | varchar(32) |      | PRI |         |       |
| Name       | varchar(30) |      |     |         |       |
+------------+-------------+------+-----+---------+-------+

charge表结构:
+-----------------+-------------+------+-----+---------+-------+
| Field           | Type        | Null | Key | Default | Extra |
+-----------------+-------------+------+-----+---------+-------+
| IdCharge        | varchar(32) |      | PRI |         |       |
| Fee             | double      | YES  |     | NULL    |       |
| ChargeTimeBegin | datetime    | YES  |     | NULL    |       |
| ChargeTimeEnd   | datetime    | YES  |     | NULL    |       |
+-----------------+-------------+------+-----+---------+-------+

在Hibernate的自带文档中有类似下面的多表查询操作提示:
“select new OjbectC(field1, field2,...) from ObjectA a, ObjectB b ...”,
分析一下可以看出这个操作有两个缺点:
    1)必须声明并创建类ObjectC,根据Hibernate的特点,需要写一个ObjectC.hbm.xml的PO映射,在只用到创建查询结果的新对象的时候,这个映射可以是个虚的,即可以没有一个真正的数据库表和ObjectC对应,但是这样的一个虚设的逻辑显然已经违背了Hibernate的思想初衷;
    2)这个办法只能查询出但条结果记录并只能创建单个的ObjectC对象,这是很局限的,因此在某些情况下根本不能使用(比如本例)。
    所以,对于本例,上面的方法是行不通的。

其实,仔细看看Hibernate的API,就会发现这个问题很好解决。在net.sf.hibernate包中有下面三个对我们很有用的接口:

1、Interface ScrollableResults
    这个接口类似JDBC中的ResultSet一样,提供了对返回结果集合的遍历和字段访问方法,如:
    public boolean next()    游标后移
    public boolean previous() 游标前移
    public boolean scroll(int i) 游标移动到指定未知
    public void beforeFirst() 游标在首记录前
    public void afterLast() 游标在末记录后
    public Object[] get() 将当前记录的字段值以Object对象数组形式返回
    public Object get(int i) 将当前记录的特定字段值以Object对象形式返回
    public Integer getInteger(int col) 将当前记录的特定字段值以Integer对象返回
    public Long getLong(int col) 将当前记录的特定字段值以Long对象返回
    public String getText(int col) 将当前记录的特定字段值以Text对象返回
    public String getString(int col) 将当前记录的特定字段值以String对象返回
    ...等等

2、Interface Query
    Query接口封装了对数据库的查询等操作,在这里,我们使用到它的原因是在于它的scroll()方法可以返回一个ScrollableResults实例:
    public ScrollableResults scroll() 将查询结果以ScrollableResults实例返回,但需要注意的是查询返回的结果其实只是一些id,当需要的时候(比如我们使用ScrollableResults.next()方法后移游标时)这条需要用到的记录才会被真正初始化(这种技术可以称作:延时初始化)

3、Interface Session
    Session是Hibernate的核心中的核心,通过Session的createQuery()方法,我们能生成一个Query实例:
    public Query createQuery(String queryString) 用给出的HQL查询串创建一个Query实例

好了,了解了上面的三个接口,问题就能够很好的解决了。需要如下几个文件:
Customer.java                            PO对象
Charge.java                                PO对象
TotalCharge.java                        用于保存统计结果Bean
Customer.hbm.xml                      PO映射
Charge.hbm.xml                          PO映射
TotalChargeDao.java                  统计Dao定义
TotalChargeDaoImpl.java           统计Dao定义实现
DaoFactory.java                         Dao工厂
HibernateSessionFactory.java     Session工厂

因为这里主要讨论的重点是对Customer和Charge的联合查询,所以Customer.java、Charge.java、Customer.hbm.xml、Charge.hbm.xml四个文件以及TotalChargeDao.java、DaoFactory.java、HibernateSessionFactory.java的源代码在这里省略掉。

TotalCharge.java 的源代码:
package test.bean;

/**
 *作者:孙星
 **/
public class TotalCharge {
  private String name;
  private Double fee;
  private java.util.Date chargeTimeBegin;
  private java.util.Date chargeTimeEnd;
  public TotalCharge() {
  }

  public String getName() {
    return name;
  }

  public TotalCharge(String name, Double fee, java.util.Date chargeTimeBegin,
                     java.util.Date chargeTimeEnd) {
    this.name = name;
    this.fee = fee;
    this.chargeTimeBegin = chargeTimeBegin;
    this.chargeTimeEnd = chargeTimeEnd;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Double getFee() {
    return fee;
  }

  public void setFee(Double fee) {
    this.fee = fee;
  }

  public java.util.Date getChargeTimeBegin() {
    return chargeTimeBegin;
  }

  public void setChargeTimeBegin(java.util.Date chargeTimeBegin) {
    this.chargeTimeBegin = chargeTimeBegin;
  }

  public java.util.Date getChargeTimeEnd() {
    return chargeTimeEnd;
  }

  public void setChargeTimeEnd(java.util.Date chargeTimeEnd) {
    this.chargeTimeEnd = chargeTimeEnd;
  }
}


TotalChargeDaoImpl.java 代码:
package test.dao.impl;

import java.util.*;
import test.bean.*;
import test.dao.*;
import net.sf.hibernate.*;

/**
 *作者:孙星
 **/
public class TotalChargeDaoImple extends TotalChargeDao{
    
    //下面方法集成自TotalChargeDao
    public List statTotalCharge(Date statTimeBegin, Date statTimeEnd) throws DaoException{
        List res = new Vector();//将用于存放保存的结果集合
        Session session = null;
        ScrollableResults srs = null;
        try{
            session = HibernateSessionFactory.openSession();//得到一个Hibernate Session
            //下面创建一个匿名Query实例并调用它的scroll()方法返回以ScrollableResults形式组织的查询结果
            srs = session.createQuery(“select b.name, count(a.fee) mix(a.chargeBeginTime) max(a.chargeEndTime) from charge a, customer b where a.idCustomer = b.idCustomer and a.chargeBeginTime >= ? and a.chargeEndTime < ? gourp by a.idCustomer“).setDate(0, statTimeBegin).setDate(1, statTimeEnd).scroll();
            //将查询结果放入List保存
            while(srs.next()){
                res.add(new TotalCharge(srs.getString(0), srs,getDouble(1), srs.getDate(2), srs.getDate(3)));
            }
        }catch(HibernateException he){
            ;//loging err.....
            if(srs!=null){
                try{
                    srs.close();
                }catch(Exception e){
                    ;
                }
            }
        }finally{
            try{
                session.close();
            }catch(Exception e){
                ;
            }
        }
        return res;
    }
}
=================原文地址:http://blog.csdn.net/weekly123/archive/2006/12/12/1439661.aspx
分享到:
评论

相关推荐

    hibernate多表联合查询

    在Hibernate中,可以使用以下几种方式来实现多表联合查询: - **HQL (Hibernate Query Language)** - **Criteria API** - **Native SQL** 本文将重点介绍如何使用HQL和Native SQL来实现多表联合查询。 #### 三、...

    Hibernate连表查询 Hibernate连表查询

    在实际开发过程中,我们经常会遇到需要从多个表中获取数据的情况,这时就需要用到连表查询。 #### 1. HBM 映射文件 在提供的内容中,出现了两个HBM映射文件:`TopProductsDeputy.hbm.xml` 和 `TopProducts.hbm.xml...

    Hibernate 多表连接分页查询示范项目

    总结,"Hibernate 多表连接分页查询示范项目"是一个实用的示例,它展示了如何在实际应用中利用 Hibernate Criteria API 实现复杂查询和分页,对于学习和掌握 Hibernate 的高级特性和数据库操作技巧非常有帮助。...

    hibernate 进行多表查询每个表中各取几个字段

    本篇文章将探讨如何在Hibernate中进行多表查询,并从每个表中选取特定的字段。 一、Hibernate的多表查询基础 在Hibernate中,多表查询通常涉及到关联关系的映射,包括一对一(OneToOne)、一对多(OneToMany)、多...

    Hibernate各种查询:联表查询 分页查询 位置参数查询(?) 占位符查询(冒号查询) 统计查询

    本篇文章将详细解析Hibernate中的几种主要查询方式,包括联表查询、分页查询、位置参数查询、占位符查询(冒号查询)以及统计查询,这些都是在实际开发中非常常见的需求。 首先,我们来看**联表查询**。在Hibernate...

    hibernate实现递归查询

    本文将深入探讨如何使用Hibernate实现递归查询,以解决在数据层次结构中涉及父节点与子节点关系时的问题。递归查询通常用于处理树形结构的数据,例如组织结构、菜单系统或者文件目录等。 首先,我们需要了解递归的...

    hibernate实现动态表查询的多种解决方案

    特别是在处理多表、多库等复杂场景时,如何实现动态表查询就显得尤为重要。本文将详细介绍几种常见的动态表查询方法,并给出具体的代码示例。 #### 二、核心概念与技术点 1. **命名策略(NamingStrategy)**:...

    Hibernate-基础联表模板

    Criteria API是Hibernate提供的另一种动态查询方式,它允许在运行时构建查询,提供了更强大的灵活性。通过DetachedCriteria、Criteria、Projection等接口,可以方便地实现联表查询,同时支持各种查询条件、排序和...

    hibernate多对多关联映射

    在Java的持久化框架Hibernate中,多对多关联映射是一种常见的关系数据库模型映射方式,用于处理两个实体之间存在多个实例互相关联的情况。本文将深入探讨Hibernate如何实现多对多关联映射,并通过实际例子解析相关...

    Hibernate(多对多表操作)

    本主题将深入探讨如何在Hibernate中处理多对多的关系映射,这是数据库设计中常见的一种关系类型。 多对多关系在数据库中意味着一个表中的记录可以与另一个表中的多个记录相关联,反之亦然。例如,学生和课程的关系...

    Hibernate多表查询.txt

    在多表查询中,查询结果往往包含来自不同表的数据,这就需要一种机制来处理这种复合类型的结果集。Hibernate提供了两种主要的方法来实现这一点: - **使用数组或列表处理结果**:如示例代码所示,查询结果可以被...

    hibernate 多表关联 中间表

    在处理多表关联时,Hibernate提供了一种高效且灵活的方法,尤其是当涉及到中间表的情况。中间表通常用于实现多对多(Many-to-Many)的关系,比如在一个用户和角色的关系中,一个用户可以有多个角色,一个角色也可以...

    Hibernate完整使用教程

    Hibernate 是一种流行的开源持久层框架,允许开发者使用面向对象编程语言来访问关系数据库。下面是关于 Hibernate 的详细知识点: Hibernate 介绍 Hibernate 是一个开源的持久层框架,它提供了一个抽象层来访问...

    hibernate实现数据库表的多种关系

    多对多关系是最复杂的一种关联,例如,学生可以选择多门课程,而课程也可以被多个学生选择。在Hibernate中,通常需要创建一个连接表来存储这种关系,并通过中间实体来管理。双方实体都会有一个集合属性,分别指向...

    Hibernate多对多关联添加及查询示例

    多对多关联是数据库设计中的一种常见关系类型,指的是两个实体之间可以存在多个对应关系。例如,在学生与课程的关系中,一个学生可以选修多门课程,而一门课程也可以被多个学生选修。在Hibernate中,这种关系通过`@...

    Hibernate中Example的用法

    `Example`查询在Hibernate中是一种非常实用且强大的查询方式,它不仅能够基于实例对象进行精确匹配,还能通过各种配置选项实现更复杂的查询需求。理解并掌握`Example`的使用,将有助于提升开发效率,同时也能让数据...

    hibernate中文参考文档

    11. Hibernate查询语言:Hibernate Query Language(HQL)是用于操作持久化数据的一种面向对象的查询语言,这部分将介绍HQL的基本语法和高级特性。 12. 条件查询:条件查询是数据库操作中常见的需求,文档会讲解...

    hibernate使用参考文档

    Hibernate 是一个流行的 Java持久层框架,它提供了一种对象关系映射(Object-Relational Mapping,ORM)机制,用于将 Java 对象与关系数据库之间建立映射关系。本文档旨在指导读者快速从 Hibernate 入门到掌握 ...

    在eclipse中使用hibernate

    ### 在Eclipse中使用Hibernate的知识点详解 #### 1. 持久化框架产生的背景和现状 在Java开发过程中,特别是在涉及数据库交互时,由于数据库本身的特性(通常是关系型数据库),与Java语言的面向对象特性之间存在...

    hibernate动态分表

    【hibernate动态分表】是一种数据库设计策略,主要用于处理大数据量的问题,通过将数据分散到多个物理表中,以实现水平扩展,提高查询效率,减轻单表的压力。在Java Web开发中,Hibernate作为一款流行的ORM(对象...

Global site tag (gtag.js) - Google Analytics