`

Hibernate多表联合查询解决办法[ZT]

阅读更多
Hibernate
是典型的OPM工具,它将每一个物理表格(Table)映射成为对象(Object),这发挥了面向对象的优势,使设计和开发人员可以从面向对象的角度来进行对数据库
的管理。
     在设计到多表操作时,Hibernate提供了与数据库表关系相对应的对象映射关系,一对一、一对多和多对多在这里都可以通过Hibernate的对象映 射关系(Set等)来实现。这为一般情况下的数据库多表操作提供了便捷途径。关于这方面的介绍已经很多,在这里不再复述。

但是,在有些情况下的多表操作,比如一个统计顾客在2005年的消费总金额的SQL操作如下:
sql 代码
  1. select    
  2. b.name count (a.fee) mix(a.chargeBeginTime)  max (a.chargeEndTime)   
  3. from    
  4. charge a, customer b   
  5. where    
  6. a.idCustomer = b.idCustomer and  a.chargeBeginTime >= '2005-01-01'   
  7. 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的自带文档中有类似下面的多表查询操作提示:
sql 代码
 
  1. 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 代码
 
  1. package  test.bean;  
  2. /**  
  3.  *作者:孙星  
  4.  **/   
  5. public   class  TotalCharge {  
  6.   private  String name;  
  7.   private  Double fee;  
  8.   private  java.util.Date chargeTimeBegin;  
  9.   private  java.util.Date chargeTimeEnd;  
  10.   public  TotalCharge() {  
  11.   }  
  12.   public  String getName() {  
  13.     return  name;  
  14.   }  
  15.   public  TotalCharge(String name, Double fee, java.util.Date chargeTimeBegin,  
  16.                      java.util.Date chargeTimeEnd) {  
  17.     this .name = name;  
  18.     this .fee = fee;  
  19.     this .chargeTimeBegin = chargeTimeBegin;  
  20.     this .chargeTimeEnd = chargeTimeEnd;  
  21.   }  
  22.   public   void  setName(String name) {  
  23.     this .name = name;  
  24.   }  
  25.   public  Double getFee() {  
  26.     return  fee;  
  27.   }  
  28.   public   void  setFee(Double fee) {  
  29.     this .fee = fee;  
  30.   }  
  31.   public  java.util.Date getChargeTimeBegin() {  
  32.     return  chargeTimeBegin;  
  33.   }  
  34.   public   void  setChargeTimeBegin(java.util.Date chargeTimeBegin) {  
  35.     this .chargeTimeBegin = chargeTimeBegin;  
  36.   }  
  37.   public  java.util.Date getChargeTimeEnd() {  
  38.     return  chargeTimeEnd;  
  39.   }  
  40.   public   void  setChargeTimeEnd(java.util.Date chargeTimeEnd) {  
  41.     this .chargeTimeEnd = chargeTimeEnd;  
  42.   }  
  43. }  
TotalChargeDaoImpl.java 代码
  1. package  test.dao.impl;  
  2. import  java.util.*;  
  3. import  test.bean.*;  
  4. import  test.dao.*;  
  5. import  net.sf.hibernate.*;  
  6. /**  
  7.  *作者:孙星  
  8.  **/   
  9. public   class  TotalChargeDaoImple  extends  TotalChargeDao{  
  10.     //下面方法集成自TotalChargeDao   
  11.     public  List statTotalCharge(Date statTimeBegin, Date statTimeEnd)  throws          DaoException{  
  12.         List res = new  Vector(); //将用于存放保存的结果集合   
  13.         Session session = null ;  
  14.         ScrollableResults srs = null ;  
  15.         try {  
  16.             //得到一个Hibernate Session   
  17.             session = HibernateSessionFactory.openSession();  
  18.   
  19.             //下面创建一个匿名Query实例并调用它的scroll()方法返回以    
  20. ScrollableResults形式组织的查询结果  
  21.             srs  
  22. = session.createQuery(“select b.name, count(a.fee)  
  23. mix(a.chargeBeginTime) max(a.chargeEndTime) from charge a, customer b  
  24. where a.idCustomer = b.idCustomer and a.chargeBeginTime >= ? and  
  25. a.chargeEndTime < ? gourp by a.idCustomer“).setDate(0 ,  
  26. statTimeBegin).setDate(1 , statTimeEnd).scroll();  
  27.   
  28.             //将查询结果放入List保存   
  29.             while (srs.next()){  
  30.                 res.add(new  TotalCharge(srs.getString( 0 ), srs,getDouble( 1 ), srs.getDate( 2 ), srs.getDate( 3 )));  
  31.             }  
  32.         }catch (HibernateException he){  
  33.             ;//loging err.....   
  34.             if (srs!= null ){  
  35.                 try {  
  36.                     srs.close();  
  37.                 }catch (Exception e){  
  38.                     ;  
  39.                 }  
  40.             }  
  41.         }finally {  
  42.             try {  
  43.                 session.close();  
  44.             }catch (Exception e){  
  45.                 ;  
  46.             }  
  47.         }  
  48.         return  res;  
  49.     }  
  50. }  

 

看,现在问题解决了。坐下来,喝杯Java吧!
分享到:
评论
4 楼 zhoulei984623 2010-09-15  
infante_yin 写道
srs.getString(0) 不报错吗?

报啥错?
3 楼 infante_yin 2010-08-10  
srs.getString(0) 不报错吗?
2 楼 zhoulei984623 2007-12-14  
应该结合视图来做可以提高效率!
1 楼 zhoulei984623 2007-11-16  
自己的例子:
DAO部分:
public List<VehicleDetail> getVehicleDetailList(String ownerId) {
      
        ArrayList<VehicleDetail> vechileDetailList = new ArrayList<VehicleDetail>();
        ScrollableResults srs = null;
      
        StringBuffer buf = new StringBuffer(100);
        buf.append("select ownerVehicleReg.vehicleID,vehicleType.name,fuelType.name,model.name,manufacture.name,vehicle.registrationNO,vehicle.assetCode,vehicle.capacity,tonnageType.name ");
        buf.append("from ownerVehicleReg in class com.bsmart.bmc.bo.admin.OwnerVehicleReg,");
        buf.append("vehicle in class com.bsmart.bmc.bo.admin.Vehicle,");
        buf.append("model in class com.bsmart.bmc.bo.admin.Model,");
        buf.append("vehicleType in class com.bsmart.bmc.bo.admin.VehicleType,");
        buf.append("manufacture in class com.bsmart.bmc.bo.admin.Manufacture,");
        buf.append("fuelType in class com.bsmart.bmc.bo.admin.FuelType,");
        buf.append("tonnageType in class com.bsmart.bmc.bo.admin.TonnageType ");
        buf.append("where ownerVehicleReg.ownerID = ");
        buf.append(ownerId );
        buf.append("and ownerVehicleReg.vehicleID = vehicle.vehicleID ");
        buf.append("and vehicle.modelId = model.modelID ");
        buf.append("and vehicle.manufactureID = manufacture.manufactureID ");
        buf.append("and vehicle.vehicleTypeID = vehicleType.vehicleTypeID ");
        buf.append("and vehicle.fuelTypeID = fuelType.FuelTypeID ");
        buf.append("and vehicle.tonnageTypeID = tonnageType.tonnageTypeID");

        srs = getSession().createQuery(buf.toString()).scroll();
      
        while(srs.next()) {
            vechileDetailList.add(new VehicleDetail(srs.getString(0),srs.getString(1),srs.getString(2),srs.getString(3),srs.getString(4),srs.getString(5),srs.getString(6),srs.getString(7),srs.getString(8)));
        }
        return vechileDetailList;
    }

VehicleDetail类:
package com.bsmart.bmc.admin.bean;

/**
*
* @author developer
*
*/
public class VehicleDetail{
  
    private String vehicleID;
    private String vehicleType;
    private String fuelType;
    private String model;
    private String manufacture;
    private String registrationNO;
    private String assetCode;
    private String capacity;
    private String tonnageType;
  
    public VehicleDetail() {
      
    }
  
    public VehicleDetail(String vehicleID,String vehicleType,String fuelType,String model,String manufacture,String registrationNO
            ,String assetCode,String capacity,String tonnageType) {
        this.vehicleID = vehicleID;
        this.vehicleType = vehicleType;
        this.fuelType = fuelType;
        this.model = model;
        this.manufacture = manufacture;
        this.registrationNO = registrationNO;
        this.assetCode = assetCode;
        this.capacity = capacity;
        this.tonnageType = tonnageType;
    }
  
    public String getAssetCode() {
        return assetCode;
    }
    public void setAssetCode(String assetCode) {
        this.assetCode = assetCode;
    }
    public String getCapacity() {
        return capacity;
    }
    public void setCapacity(String capacity) {
        this.capacity = capacity;
    }
    public String getFuelType() {
        return fuelType;
    }
    public void setFuelType(String fuelType) {
        this.fuelType = fuelType;
    }
    public String getManufacture() {
        return manufacture;
    }
    public void setManufacture(String manufacture) {
        this.manufacture = manufacture;
    }
    public String getModel() {
        return model;
    }
    public void setModel(String model) {
        this.model = model;
    }
    public String getRegistrationNO() {
        return registrationNO;
    }
    public void setRegistrationNO(String registrationNO) {
        this.registrationNO = registrationNO;
    }
    public String getTonnageType() {
        return tonnageType;
    }
    public void setTonnageType(String tonnageType) {
        this.tonnageType = tonnageType;
    }
    public String getVehicleID() {
        return vehicleID;
    }
    public void setVehicleID(String vehicleID) {
        this.vehicleID = vehicleID;
    }
    public String getVehicleType() {
        return vehicleType;
    }
    public void setVehicleType(String vehicleType) {
        this.vehicleType = vehicleType;
    }

相关推荐

    hibernate多表联合查询

    ### Hibernate多表联合查询详解 #### 一、引言 在实际项目开发中,我们经常需要处理复杂的数据库查询,特别是涉及到多个表之间的关联查询。Hibernate作为一款流行的Java持久层框架,提供了一种非常便捷的方式来处理...

    Hibernate连表查询 Hibernate连表查询

    根据提供的文件信息,我们可以深入探讨Hibernate中的连表查询方法及其应用。下面将详细介绍与标题、描述及部分代码相关的几个核心知识点: ### Hibernate 连表查询基础 Hibernate 是一个开源的对象关系映射(ORM)...

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

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

    hibernate 多表查询

    hibernate 多表查询 hibernate 多表不同于一般的sql嵌套查询,嵌套查询是不支持的,所以必须要配置好才能实现多表!只要配置好了,还是特别好用的

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

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

    多表联合查询

    ### 多表联合查询在Hibernate中的应用 #### 一、多表联合查询概述 多表联合查询是指在数据库操作中,通过SQL语句将多个表中的数据进行组合查询的技术。这种方式能够有效地解决复杂业务场景下的数据整合问题。在...

    hibernate代码优化基于配置的多表查询

    本文将深入探讨如何通过配置优化Hibernate的多表查询,以提高应用的性能。 1. **联合查询优化**: 在进行多表查询时,Hibernate默认可能会生成多个单表查询,这会导致大量的数据库往返,降低效率。通过配置`@Join...

    Hibernate多表查询.txt

    本文将深入探讨Hibernate中的多表查询技术,解析其背后的原理与实践方法,帮助开发者更好地掌握这一核心技能。 ### Hibernate多表查询概述 在现实世界的应用场景中,数据往往不会孤立存在,而是通过关联分布在多个...

    Hibernate联合主键的例子

    在Java持久化框架Hibernate中,联合主键(Composite Key)是一种特殊的数据结构,用于标识数据库表中的一条记录。与单个字段作为主键不同,联合主键由两个或更多个字段共同组成,形成一个唯一的标识。在本教程中,...

    hibernate N+1问题解决办法

    **标题:“Hibernate N+1问题解决办法”** 在Java开发中,使用Hibernate作为ORM框架时,我们可能会遇到一个性能上的问题,那就是著名的“N+1查询问题”。此问题源于不恰当的数据加载策略,可能导致数据库查询效率...

    day36 04-Hibernate检索方式:多表连接查询

    标题中的“day36 04-Hibernate检索方式:多表连接查询”表明这是一个关于Hibernate框架的教程,重点讲解如何在Hibernate中进行多表连接查询。在这个主题中,我们将深入探讨Hibernate的ORM(对象关系映射)机制以及...

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

    本示例主要关注的是Hibernate中的多对多关联映射及其添加与查询方法。 多对多关联是数据库设计中的一种常见关系类型,指的是两个实体之间可以存在多个对应关系。例如,在学生与课程的关系中,一个学生可以选修多门...

    hibernate联合主键全攻略

    - **查询**:使用`createCriteria()`结合`Restrictions.eq()`等条件过滤器进行查询,注意当查询联合主键的一部分时,可能需要额外处理以避免结果集的不确定性。 #### 4. 特别注意事项 - 在使用联合主键时,确保...

    Hibernate-基础联表模板

    "Hibernate-基础联表模板"是针对Hibernate中联表查询的一个实用工具,旨在帮助开发者快速地进行多表关联查询,而不必记住复杂的SQL语句。 1. **Hibernate简介** Hibernate是一种开源的ORM框架,它允许开发者将Java...

    Hibernate_query查询数据表中的一个字段.

    本篇将详细讲解如何使用Hibernate进行查询,特别是针对数据表中的一个特定字段。 一、Hibernate简介 Hibernate是Java领域的一个开源ORM框架,它简化了数据库操作,通过映射Java类到数据库表,可以将数据库操作转化...

    struts2+hibernate+spring多表操作示例

    4. **多表查询与操作**:在多表关联的场景下,常见的操作有联合查询、级联保存/更新和级联删除。例如,通过Hibernate的 Criteria 或 HQL 查询语言,可以方便地执行多表的JOIN操作。级联保存时,只需要保存父对象,...

    hibernate多表查询[定义].pdf

    在本案例中,我们关注的是Hibernate中的多表查询,这是在处理复杂数据关系时常见的需求。 多表查询涉及到了三个或更多的表之间的关联,这在现实世界的业务场景中很常见,如学生信息与班级信息的关联。在Hibernate中...

    hibernate实现动态SQL查询

    例如,我们可以为一个实体类定义多个HQL或SQL查询,根据实际需要选择执行哪一个。 五、FREEMARKER解析 FREEMARKER是一款强大的模板引擎,常用于Web应用中的视图渲染。在Hibernate中,我们可以利用FREEMARKER生成...

    hibernate的联合主键怎么设置

    在 Hibernate 中,联合主键(Composite Key)是指由两个或多个属性共同构成的主键,这种主键在数据库设计中常见于需要多个字段唯一标识一条记录的情况。在 Hibernate 中设置联合主键通常需要以下几个步骤: 1. **...

    Hibernate错误及解决办法集合

    ### Hibernate常见错误及解决办法 #### 一、Nodefaultconstructorforentity 错误 **问题描述**:在使用Hibernate执行查询语句时,系统抛出`Nodefaultconstructorforentity`错误。 **可能原因**:该错误通常是由于...

Global site tag (gtag.js) - Google Analytics