`

使用 hibernate SQL Query实现动态表

阅读更多
我在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。而 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 写到配置文件中,根据不同的数据库,装载相应的配置文件咯。

分享到:
评论

相关推荐

    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 query.pdf

    hibernate sql hqlsql

    Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法

    ### Hibernate SQLQuery 查询Oracle char类型结果为一个字符的解决方法 在使用Hibernate框架结合Oracle数据库进行数据查询时,经常会遇到一个问题:当查询的结果集中包含char类型的字段时,Hibernate可能会将其映射...

    hibernate执行原生sql语句

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

    Hibernate中Sql语句

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

    Hibernate+本地SQL查询SQLQuery宣贯.pdf

    在某些情况下,开发者可能需要使用原生SQL查询来执行特定的数据库操作,这时就可以利用Hibernate的SQLQuery功能。本文将详细讲解如何使用Hibernate的SQLQuery进行本地SQL查询。 首先,创建SQLQuery实例是通过...

    hibernate增删改查和动态sql

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

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

    SQLQuery query = session.createSQLQuery(sql); ``` 如果查询返回的是单个对象,我们可以使用`addEntity()`方法指定结果应映射到的实体类: ```java query.addEntity(MyEntity.class); MyEntity result = ...

    Hibernate_query聚合函数查询.

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

    hibernate 实践 Query详解

    在这个“hibernate 实践 - Query详解”的主题中,我们将深入理解如何使用Query接口来执行SQL查询,并绑定参数。 1. **Query接口** Query接口是Hibernate提供的一种用于执行HQL(Hibernate查询语言)或SQL查询的API...

    hibernate数据库通用SQL代码

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

    使用Hibernate访问sqlserver数据库

    **使用Hibernate访问SQL Server数据库** Hibernate是一个开源的对象关系映射(ORM)框架,它为Java开发者提供了一种在关系数据库和面向对象编程之间架起桥梁的方式。通过使用Hibernate,我们可以避免编写大量的SQL...

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

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

    Native SQL查询 (使用SQLQuery).doc

    在 Hibernate 中,使用 SQLQuery 可以执行 Native SQL 查询,控制查询的执行是通过 SQLQuery 接口进行的,通过执行 Session.createSQLQuery() 获取这个接口。下面将详细介绍如何使用这个 API 进行查询。 标量查询...

    Hibernate+本地SQL查询SQLQuery.pdf

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

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

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

    hibernate 执行原生sql的几种方式

    SQLQuery query = session.createSQLQuery("SELECT * FROM User"); List results = query.list(); ``` 这种方法可以自由地编写任何有效的SQL,但需要手动映射查询结果到Java对象。如果返回结果需要映射到实体类...

Global site tag (gtag.js) - Google Analytics