`
Callan
  • 浏览: 736597 次
  • 性别: Icon_minigender_1
  • 来自: 上海
社区版块
存档分类
最新评论

使用hibernate SQLQuery实现动态表

    博客分类:
  • Java
阅读更多
我在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。而 hibernate 提供的类与表的映射,是只能映射到一个具体表的,在程序的运行过程中,很难去动态修改一个 hbm 对应的表名。我在网上也有看到一实现,但是很复杂,并且不符合我的要求。
因此我就想到直接用 jdbc 去操作数据库,这样的做法是绕过 hibernate 了。方法是从 hibernate 的 session 中,直接取得数据库 connection ,然后就直接 jdbc 了。
后来在升级了 proxool 到 9.0RC3 后,发现居然出现了数据库连接无法释放的问题。为了解决这个问题,我查阅了 hibernate doc。我发现原来用 SQLQuery 可以更好的解决,并且可以重新用于 hibernate hbm 机制。以下举例说明。
例如我有一个 pojo 是 ReadInfo,用来记录阅读信息的。由于数据量宠大,所以我的思路是按月划分,每个月一张表。所以只是表名不同,而字段是完全相同的。
ReadInfo.java 是这样的,其中 userId, year, month, day 是联合主键:

    private Integer userId;
    private Integer year;
    private Integer month;
    private Integer day;
    private Integer point;

那么相应的 ReadInfo.hbm.xml 的片段是

    <class name="ReadInfo" table="tblReadInfo" mutable="false">
        <composite-id>
            <key-property name="userId" column="userId" type="integer"/>
            <key-property name="year" column="year" type="integer"/>
            <key-property name="month" column="month" type="integer"/>
            <key-property name="day" column="day" type="integer"/>
        </composite-id>
        <property name="point" column="point" type="integer"/>
    </class>

上面的xml,注意 2 个细节

1. pojo 所映射的 table tblReadInfo 实际上是不存在的。实际的表是 tblRead200710 之类的;

2. mutable 要设置为 false,即是说,关闭 hibernate 对这个 pojo 的任何持久化操作,以避免 hibernate 把数据写到 tblReadInfo 中(这个表是不存在的嘛)。因此,所有的持久化操作,都是需要自己通过 SQLQuery 来处理。

现在可以看一下 ado 中的操作了,先看一个 select 操作

public ReadInfo selectReadInfo(Integer userId, Integer year,
            Integer month, Integer day) throws HibernateException
    {
        ReadInfo readInfo = null;

        Session session = getSession();
        Transaction tx = session.beginTransaction();

        try
        {
            String sql = "select * from tblRead"
                + Misc.formatMoon(year, month)
                + " where userId=? and day=?";

            SQLQuery query = session.createSQLQuery(sql);
            query.addEntity(ReadInfo.class);

            query.setLong(0, userId);
            query.setInteger(1, day);

            readInfo = (ReadInfo) query.uniqueResult();

            tx.commit();
        }
        catch (HibernateException e)
        {
            log.error("catch exception:", e);

            if (tx != null)
            {
                tx.rollback();
            }

            throw e;
        }
        return readInfo;
    }

上面的代码,关键是以下几点:

1. 通过函数参数的 year, month 来确定要操作的表名,我自己写了一个 Misc.formatMoon(year, month) 来生成 "yyyyMM" 格式的字串;

2. 使用了 SQLQuery ,再通过 query.addEntity(ReadInfo.class); 建立与 ReadInfo 的映射关系;

3. query.setXxx() 与 PreparedStatement 的类似,不过索引是从 0 开始;

4. 其它的就跟一般的 Query 操作类似的了。

再看一个 insert 操作

    public void insertReadInfo(ReadInfo readInfo) throws HibernateException
    {
        Session session = getSession();
        Transaction tx = session.beginTransaction();

        try
        {
            String sql = "insert into tblRead"
                + Misc.formatMoon(readInfo.getYear(), readInfo.getMonth())
                + " (userId, year, month, day, point) values (?, ?, ?, ?, ?)";

            SQLQuery query = session.createSQLQuery(sql);

            query.setLong(0, readInfo.getUserId());
            query.setInteger(1, readInfo.getYear());
            query.setInteger(2, readInfo.getMonth());
            query.setInteger(3, readInfo.getDay());
            query.setInteger(4, readInfo.getPoint());

            query.executeUpdate();

            tx.commit();
        }
        catch (HibernateException e)
        {
            log.error("catch exception:", e);

            if (tx != null)
            {
                tx.rollback();
            }

            throw e;
        }
    }

同理,update, delete 等操作也是这样实现的。

hmm.. 这种处理方式的麻烦的地方是需要手工写 sql ,因此要尽量写通用的标准 sql,不然在数据库兼容方面会有问题。当然,有时是会出现无法兼容的情况,那么可以考虑把 sql 写到配置文件中,根据不同的数据库,装载相应的配置文件咯。

5
0
分享到:
评论
5 楼 z6978445 2015-02-10  
查询呢?比如要查出 tblRead200710 表与 tblRead200711 表的数据,并且支持分页显示???
4 楼 jespring 2010-08-11  
太好了。要早点看到就好了。害得我配置了好多个pojo。谢谢
3 楼 marssstone 2008-09-16  
POJO类如果有SET和GET方法是否影响?
2 楼 marssstone 2008-09-16  
是否要讲hbm.xml配置在hibernate.cfg.xml中
1 楼 marssstone 2008-09-16  
楼主能否发份代码,感激不尽

邮箱 harryyang1986@sina.com

谢谢了

相关推荐

    hibernate实现动态SQL查询

    为了实现动态SQL,我们可以借助于Hibernate的QBC(Query By Criteria)和Criteria API,或者使用第三方库如MyBatis的动态SQL功能。本文主要讨论使用XML配置和FREEMARKER的方法。 四、XML配置SQL 在Hibernate中,...

    Hibernate SQLQuery 本地查询

    这篇博客"Hibernate SQLQuery 本地查询"可能详细讲解了如何利用Hibernate的SQLQuery类来执行SQL查询,以及如何在实际项目中结合BaseDaoSupport类实现数据访问。 首先,让我们理解SQLQuery的基本用法。在Hibernate中...

    Hibernate SQLQuery执行原生SQL.docx

    在Java的Hibernate框架中,有时候我们需要执行自定义的SQL查询以获取特定的数据,这时就可以使用SQLQuery接口。本文将深入探讨Hibernate如何通过SQLQuery接口执行原生SQL查询,并展示如何处理查询结果。 一、创建...

    hibernate执行原生sql语句

    Hibernate 提供了多种方式来执行原生 SQL 语句,其中之一是使用 `Session.createSQLQuery()` 方法,该方法返回一个 `SQLQuery` 对象,该对象提供了执行原生 SQL 语句的方法。 例如,我们可以使用以下代码来执行一个...

    Hibernate中Sql语句

    ### Hibernate中使用SQL而非HQL语句的知识点详解 在Java开发中,Hibernate作为一个非常流行的ORM框架,提供了多种查询方式,其中就包括了HQL(Hibernate Query Language)和原生SQL查询。本文将针对给定代码片段中...

    hibernate增删改查和动态sql

    6. **Maven Webapp:** 提到的"curd2 Maven Webapp"可能是指一个使用Maven构建的Web应用程序,其中包含了一个名为"curd2"的模块,这个模块可能包含了上述关于Hibernate CRUD操作和动态SQL的实现。 综上所述,这个...

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

    本文介绍了三种利用Hibernate实现动态表查询的方法:自定义命名策略、使用拦截器以及利用Session的开放性。每种方法都有其适用场景,开发者可以根据实际需求选择最合适的一种。例如,在需要频繁更改表名的情况下,...

    Hibernate+本地SQL查询SQLQuery.pdf

    在Java的持久化框架Hibernate中,有时我们需要使用原生的SQL查询来实现特定的数据库操作,这时就需要利用到SQLQuery接口。本篇文章将详细解析如何使用Hibernate的SQLQuery来进行本地SQL查询,并探讨其各种应用场景。...

    Hibernate_query聚合函数查询.

    首先,让我们了解一下Hibernate中的HQL(Hibernate Query Language),它是Hibernate提供的面向对象的查询语言,类似于SQL,但更贴近于Java。在HQL中,我们可以方便地使用聚合函数进行数据处理。例如,如果你想要...

    Hibernate_query查询数据表中部分字段.

    本文将深入探讨如何使用Hibernate进行数据表中的部分字段查询,这在实际开发中是非常常见的需求。 首先,理解Hibernate的核心概念:实体(Entity)、持久化类(Persistent Class)和映射文件(Mapping File)。实体...

    hibernate数据库通用SQL代码

    查询数据的方法有两种实现,一种是基于HQL(Hibernate Query Language),另一种是基于原生SQL。 - 基于HQL的通用查询: HQL是Hibernate提供的面向对象的查询语言,可以方便地操作对象和属性。`select`方法接收一个...

    Hibernate连表查询 Hibernate连表查询

    除了使用HQL外,还可以选择直接使用原生SQL来执行连表查询。例如,在`findAllbyString`方法中,使用了`getSession().createSQLQuery`方法来执行原生SQL查询: ```java String queryString = "Select * from h_...

    hibernate多表联合查询

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

    hibernate 连接sqlserver2000

    标题 "Hibernate 连接 SQLServer2000" 暗示了我们将探讨如何使用流行的Java ORM框架Hibernate与较老版本的SQL Server数据库——SQL Server 2000进行交互。在Java应用程序开发中,Hibernate提供了对象关系映射功能,...

    Hibernate+sqlserver2000分页

    `Criteria API` 是一种更加灵活和类型安全的查询方式,可以替代传统的HQL(Hibernate Query Language)来构建动态查询。而`Pagination`则是处理大量数据时,分批次获取结果的策略。 1. **Criteria API 分页**: ...

    hibernate动态数据库改进版

    Hibernate是一个开源的ORM框架,它允许开发者使用面向对象的方式来操作数据库,通过映射机制将Java对象与数据库表进行对应,从而避免了繁琐的SQL语句编写。 1.2 动态数据库需求 在实际开发中,我们可能需要根据用户...

    Hibernate生产SQL语句

    Hibernate的核心在于它的Query API,它提供了Criteria、HQL(Hibernate Query Language)和JPQL(Java Persistence Query Language)等方式来构建SQL语句。Hibernate会根据这些查询语句动态生成对应的SQL,并执行在...

    \Hibernate_query条件查询

    HQL是Hibernate提供的面向对象的查询语言,类似于SQL,但操作的对象是对象而非表。例如,要获取所有用户,可以使用以下HQL语句: ```java Query query = session.createQuery("from User"); List&lt;User&gt; users = ...

    Hibernate方法的实现

    - **查询(Query)**:使用Criteria API或HQL(Hibernate Query Language)进行查询。例如,使用Session的createCriteria()或createQuery()方法,然后添加查询条件,最后调用list()或uniqueResult()获取结果。 6. ...

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

    Hibernate 支持多种方式来实现多表连接查询,包括 HQL(Hibernate Query Language)和 Criteria 查询。本项目主要关注 Criteria API 的使用,这是一种基于 Java 对象的查询方式,更加灵活且易于理解和维护。 **...

Global site tag (gtag.js) - Google Analytics