在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。而 Hibernate 提供的类与表的映射,是只能映射到一个具体表的,在程序的运行过程中,很难去动态修改一个 hbm 对应的表名。我在网上也有看到一实现,但是很复杂,并且不符合我的要求。

创新互联是一家从事企业网站建设、成都网站设计、网站制作、行业门户网站建设、网页设计制作的专业网络公司,拥有经验丰富的网站建设工程师和网页设计人员,具备各种规模与类型网站建设的实力,在网站建设领域树立了自己独特的设计风格。自公司成立以来曾独立设计制作的站点近千家。
因此我就想到直接用 jdbc 去操作数据库,这样的做法是绕过 Hibernate 了。方法是从 Hibernate 的 session 中,直接取得数据库 connection ,然后就直接 jdbc 了。
后来在升级了 proxool 到 9.0RC3 后,发现居然出现了数据库连接无法释放的问题。为了解决这个问题,我查阅了 Hibernate doc。我发现原来用Hibernate 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 中(这个表是不存在的嘛)。因此,所有的持久化操作,都是需要自己通过Hibernate 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 等操作也是这样通过Hibernate SQLquery来实现的。
这种Hibernate SQLquery处理方式的麻烦的地方是需要手工写 SQL,因此要尽量写通用的标准SQL,不然在数据库兼容方面会有问题。当然,有时是会出现无法兼容的情况,那么可以考虑把 SQL写到配置文件中,根据不同的数据库,装载相应的配置文件。
【编辑推荐】
                新闻名称:使用Hibernate SQLquery实现动态表
                
                链接地址:http://www.csdahua.cn/qtweb/news47/99547.html
            
网站建设、网络推广公司-快上网,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等
声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 快上网