`

hibernate使用from (select ……)子查询的方法

    博客分类:
  • Java
阅读更多

今天徒弟用到了一句复杂的查询语句。。。。结果执行报错,但是在SQL中执行没有问题,于是来求助我了。。。

语句的HQL/SQL格式如下:

select count(1) ,cxltype,sum(dzsje),sum(iperson)from (select xl.cxltype,g.iperson,(select sum(y.dzsje) from Ysklist as y where y.cykpid = g.cregno) as dzsje from Guestreg as g,Xl as xl where g.xluuid = xl.uuid   ) as t where  …… group by t.cxltype

结果执行出错,最终发现,HQL无法支持from后面跟子查询的方式,网上查了N多资料,发现遇到这个问题的人还真是不少,但每一个相关的问题帖都没有满意的答复,甚至于多数都是没有跟帖的。。。。

 

一阵心寒,hibernate叱咤风云,竟然对这个支持如此之弱?虽然这个语句可以通过另外的方法来做(比如建视图或者直接使用SQL来做),但总是不甘心,于是又开始查阅各处资料,最后找到了思路,觉得既然HQL不支持,那么只能把这种子查询封装为对象来做了,那么肯定是需要hbm配置这种临时的子查询对象的,于是开始着手hbm配置的资料中查,hbm中配置对象的都是class标签,开始把范围缩小,针对hbm的class标签的属性资料开始翻查,找到了几个比较可能的属性,where、subselect、mutable、entity-bean,貌似这些都可能跟临时对象有关。。。

 

于是反复尝试,并继续翻查资料

最终在Hibernate reference 3.2.0 ga 正式版中文参考手册中找到了一些比较可靠的资料:

5.1.3. class

你可以使用class元素来定义一个持久化类:

<class
        name="ClassName"
        table="tableName"
        discriminator-value="discriminator_value"
        mutable="true|false"
        schema="owner"
        catalog="catalog"
        proxy="ProxyInterface"
        dynamic-update="true|false"
        dynamic-insert="true|false"
        select-before-update="true|false"
        polymorphism="implicit|explicit"
        where="arbitrary sql where condition"
        persister="PersisterClass"
        batch-size="N"
        optimistic-lock="none|version|dirty|all"
        lazy="true|false"
        entity-name="EntityName"
        check="arbitrary sql check condition"
        rowid="rowid"
        subselect="SQL expression"
        abstract="true|false"
        node="element-name"
/>
1

name (可选): 持久化类(或者接口)的Java全限定名。 如果这个属性不存在,Hibernate将假定这是一个非POJO的实体映射。

2

table (可选 - 默认是类的非全限定名): 对应的数据库表名。

3

discriminator-value (可选 - 默认和类名一样): 一个用于区分不同的子类的值,在多态行为时使用。它可以接受的值包括 nullnot null

4

mutable (可选,默认值为true): 表明该类的实例是可变的或者不可变的。

5

schema (可选): 覆盖在根<hibernate-mapping>元素中指定的schema名字。

6

catalog (可选): 覆盖在根<hibernate-mapping>元素中指定的catalog名字。

7

proxy (可选): 指定一个接口,在延迟装载时作为代理使用。 你可以在这里使用该类自己的名字。

8

dynamic-update (可选, 默认为 false): 指定用于UPDATE 的SQL将会在运行时动态生成,并且只更新那些改变过的字段。

9

dynamic-insert (可选, 默认为 false): 指定用于INSERT的 SQL 将会在运行时动态生成,并且只包含那些非空值字段。

10

select-before-update (可选, 默认为 false): 指定Hibernate除非确定对象真正被修改了(如果该值为true-译注),否则不会执行SQL UPDATE操作。在特定场合(实际上,它只在一个瞬时对象(transient object)关联到一个 新的session中时执行的update()中生效),这说明Hibernate会在UPDATE 之前执行一次额外的SQL SELECT操作,来决定是否应该执行 UPDATE

11

polymorphism(多态) (可选, 默认值为 implicit (隐式) ): 界定是隐式还是显式的使用多态查询(这只在Hibernate的具体表继承策略中用到-译注)。

12

where (可选) 指定一个附加的SQLWHERE 条件, 在抓取这个类的对象时会一直增加这个条件。

13

persister (可选): 指定一个定制的ClassPersister

14

batch-size (可选,默认是1) 指定一个用于 根据标识符(identifier)抓取实例时使用的"batch size"(批次抓取数量)。

15

optimistic-lock(乐观锁定) (可选,默认是version): 决定乐观锁定的策略。

(16)

lazy (可选): 通过设置lazy="false", 所有的延迟加载(Lazy fetching)功能将被全部禁用(disabled)。

(17)

entity-name (可选,默认为类名): Hibernate3允许一个类进行多次映射( 前提是映射到不同的表),并且允许使用Maps或XML代替Java层次的实体映射 (也就是实现动态领域模型,不用写持久化类-译注)。 更多信息请看第 4.4 节 “动态模型(Dynamic models)” and 第 18 章 XML映射

(18)

check (可选): 这是一个SQL表达式, 用于为自动生成的schema添加多行(multi-row)约束检查

(19)

rowid (可选): Hibernate可以使用数据库支持的所谓的ROWIDs,例如: Oracle数据库,如果你设置这个可选的rowid, Hibernate可以使用额外的字段rowid实现快速更新。ROWID是这个功能实现的重点, 它代表了一个存储元组(tuple)的物理位置。

(20)

subselect (可选): 它将一个不可变(immutable)并且只读的实体映射到一个数据库的 子查询中。当你想用视图代替一张基本表的时候,这是有用的,但最好不要这样做。更多的介绍请看下面内容。

(21)

abstract (可选): 用于在<union-subclass>的继承结构 (hierarchies)中标识抽象超类。

 

注意其中红色的字体,这就是关键之处,往下我找到了相关的内容:

 

对Hibernate映射来说视图和表是没有区别的,这是因为它们在数据层都是透明的( 注意:一些数据库不支持视图属性,特别是更新的时候)。有时你想使用视图,但却不能在数据库 中创建它(例如:在遗留的schema中)。这样的话,你可以映射一个不可变的(immutable)并且是 只读的实体到一个给定的SQL子查询表达式:

<class name="Summary">
    <subselect>
        select item.name, max(bid.amount), count(*)
        from item
        join bid on bid.item_id = item.id
        group by item.name
    </subselect>
    <synchronize table="item"/>
    <synchronize table="bid"/>
    <id name="name"/>
    ...
</class>

定义这个实体用到的表为同步(synchronize),确保自动刷新(auto-flush)正确执行, 并且依赖原实体的查询不会返回过期数据。<subselect>在属性元素 和一个嵌套映射元素中都可见。

 

显然这就是我一直在找的东东了,hibernate支持自身建立视图,而不需要依赖于数据库。。虽然它本身的说法这是用来替代视图的,但其实这就是带子查询的sql,看我们最终的配置结果。

临时子查询视图Bean[其中第二个非默认的构造函数是不能少的,不然对象无法创建]:

 

public class TestBean {
    private Integer id;
    private String cxltype;
    private Integer iperson;
    private Double dzsje;
    public TestBean(){}
    
    public TestBean(String cxltype, Integer iperson, Double dzsje) {
        super();
        this.cxltype = cxltype;
        this.iperson = iperson;
        this.dzsje = dzsje;
    }
    public String getCxltype() {
        return cxltype;
    }
    public void setCxltype(String cxltype) {
        this.cxltype = cxltype;
    }
    public Integer getIperson() {
        return iperson;
    }
    public void setIperson(Integer iperson) {
        this.iperson = iperson;
    }
    public Double getDzsje() {
        return dzsje;
    }
    public void setDzsje(Double dzsje) {
        this.dzsje = dzsje;
    }

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }
}

 

 

 

TestBean的hbm配置:

 

<hibernate-mapping>
    <class name="TestBean" mutable="false">
    <subselect>
        select xl.cxltype,g.iperson,(select sum(y.dzsje) from Ysklist as y where y.cykpid = g.cregno) as dzsje 
        from Guestreg as g,Xl as xl 
        where g.xluuid = xl.uuid
    </subselect>
    <synchronize table="Guestreg"/>
    <synchronize table="Xl"/>
        <id name="id" type="integer">
            <column name="id" />
            <generator class="identity" />
        </id>
        <property name="cxltype" type="string">
            <column name="cxltype"></column>
        </property>
        <property name="iperson" type="integer">
            <column name="iperson"></column>
        </property>
        <property name="dzsje" type="double">
            <column name="dzsje"></column>
        </property>
    </class>
</hibernate-mapping>

 

 

 

 

 

 

HQL语句:

select t.cxltype,sum(t.dzsje),sum(t.iperson) from TestBean as t where …… group by t.cxltype

Hibernate生成的SQL语句:

Hibernate: select testbean0_.cxltype as col_0_0_, sum(testbean0_.dzsje) as col_1_0_, sum(testbean0_.iperson) as col_2_0_ from (
     select xl.cxltype,g.iperson,(select sum(y.dzsje) from Ysklist as y where y.cykpid = g.cregno) as dzsje
     from Guestreg as g,Xl as xl
     where g.xluuid = xl.uuid
     ) testbean0_ where 1=1 group by testbean0_.cxltype
可以看得出来,这就是文章最开始要完成的SQL子查询语句

到此告一段落,花了我半个下午的时间搞定。。。

 

而这个问题也是很久以前我一开始就怀疑hibernate的HQL灵活性的一个困惑,一直觉得Hibernate在多表查询上是一个弱项,但我也一直没有找时间去深究过,而经过这次问题,让我对Hibernate又多认识了一些。。呵呵,以后可以更放心的去用它了

 

5
0
分享到:
评论
4 楼 bingo6001 2010-12-21  
org.springframework.orm.hibernate3.HibernateQueryException:
K3K4Kxtbb is not mapped,可实际上我已经定义了K3K4Kxtbb.hbm.xml以及K3K4Kxtbb 类
附配置文件:
<hibernate-mapping>
    <class name="K3K4Kxtbb" mutable="false">
    <subselect>
    select k3.*,'no' as st from k3_kxtbb k3
union
select k4.*,'yes' as st from k4_kxtbb k4
    </subselect>
    <synchronize table="K4Kxtbb"/>
    <synchronize table="K3Kxtbb"/>
         <!-- 省略属性 -->
    </class>
</hibernate-mapping>
3 楼 欣水寓言 2009-10-19  
zgz888 写道
如何在SQL里面加参数呢?

参数建议放在外面的form中
2 楼 zgz888 2009-10-16  
如何在SQL里面加参数呢?
1 楼 truddy 2009-09-07  
   我也遇到过这样的问题,但是最终是把from子查询改到where子查询里面去了

相关推荐

    hibernate子查询

    在面对这种限制时,一种解决方法是通过转换查询逻辑,避免直接在`FROM`后面使用子查询。例如,可以创建视图来存储子查询的结果,然后在HQL中直接引用这个视图。另一种方法是改用原生的SQL查询,利用Hibernate的`...

    Hibernate 函数 ,子查询 和原生SQL查询

    2. **比较操作符**:`from Entity e where e.value &gt; (select avg(value) from Entity)`,可以比较当前实体的值与子查询的平均值。 3. **EXISTS/NOT EXISTS**:`from Entity e where exists (select 1 from ...

    Hibernate连表查询 Hibernate连表查询

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

    hibernate多表联合查询

    使用HQL进行多表联合查询是非常直观的,我们可以直接使用`FROM`子句来指定要查询的表,然后使用`JOIN`子句来连接不同的表。示例如下: ```java // 假设Customer和Charge实体类已定义好 Session session = ...

    hibernate里面的 两种查询

    可以使用`select`指定返回的结果,`where`后跟查询条件,`order by`进行排序。例如:`from User where age &gt; 18 order by name`。 3. 对比与选择: - Criteria API 更加面向对象,适合于简单的查询,或者在不熟悉...

    hibernate查询方法

    **Hibernate查询方法大全** Hibernate,作为Java领域中最流行的持久化框架之一,提供了多种查询数据的方法。这些方法使得开发者能够高效地从数据库中检索、更新和删除数据,无需编写大量SQL语句。本篇文章将深入...

    通用的hibernate查询

    除了基础的查询,Hibernate还支持连接查询、子查询、聚合函数等高级功能。例如,如果你需要根据用户的年龄进行分组并计算每个年龄段的用户数量,可以这样写: ```java String hql = "select age, count(*) from ...

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

    总结,Hibernate提供多种方式查询数据表中的字段,包括HQL、Criteria API和DetachedCriteria,选择合适的方法取决于具体需求。正确理解和使用Hibernate,能够大大提高Java开发中的数据库操作效率。

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

    而`HQL`则可以直接使用`select count(*) from Entity`获取总数。 总的来说,Hibernate的`Criteria`、`Query`以及QBC(Query By Criteria)提供了灵活且强大的查询手段,它们不仅支持基本的单表查询,还能处理复杂的...

    hibernate实现递归查询

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

    hibernate的配置使用和各种查询

    ### Hibernate的配置与使用详解 #### 一、Hibernate概述 Hibernate是一种开源的对象关系映射(Object-Relational Mapping,简称ORM)框架,它为Java应用提供了利用SQL数据的持久化解决方案。通过ORM技术,开发人员...

    Oracle中(column1,column2..)in(集合/子查询)的hibernate实现

    总的来说,这篇文章可能会深入探讨如何使用Hibernate的Criteria API来构建多列`IN`查询,包括与子查询的结合,以及如何处理可能存在的`NULL`值问题。这对于理解和优化Hibernate的查询性能至关重要,特别是在处理大...

    hibernate3.2 (十)HQL查询

    2. 子查询:可以在HQL中嵌套查询,例如`select u from User u where u.id in (select a.userId from Address a where a.city='上海')`,找出所有有上海地址的用户。 3. 排序:使用`order by`子句可以对查询结果进行...

    hibernate将本地SQL查询结果封装成对象(最终)

    使用本地sql语句查询后,无需再使用Object对查询结果进行强制转换,而是直接将查询结果放到实体Bean里了。 PS: 其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在...

    hibernate将本地SQL查询结果封装成对象

    首先,本地SQL查询(Native SQL)是指直接在Hibernate中使用原生的SQL语句进行查询,而不是使用HQL(Hibernate Query Language)。这允许开发者充分利用SQL的功能,比如进行复杂的统计计算或者处理特定数据库的特性...

    Hibernate 参数查询通用方法

    本篇将详细探讨"Hibernate参数查询通用方法"这一主题,以及如何通过Dao层实现高效、灵活的数据查询。 在Hibernate中,参数查询通常涉及到HQL(Hibernate Query Language)或者使用Criteria API。这两种方式都可以...

    Hibernate查询解决方案

    Hibernate 的核心功能之一是提供了一套强大的查询接口和方法,包括基于对象的查询、SQL 查询和 HQL (Hibernate Query Language) 查询等。本文将详细介绍 Hibernate 提供的几种查询方式及其应用场景。 #### 二、重要...

    hibernate实现动态SQL查询

    在Hibernate中,我们通常使用HQL(Hibernate Query Language)或Criteria API进行查询,但这些方式并不支持复杂的动态查询。为了实现动态SQL,我们可以借助于Hibernate的QBC(Query By Criteria)和Criteria API,...

    用jsp开发与实现教学管理系统

    第一章 前言………………………………………………………………………………………………… 3 第二章 Servlet简介 1. 什么是Servlet……………………………………………………………………………………… 3 2. ...

Global site tag (gtag.js) - Google Analytics