新聞中心
在實(shí)際的項(xiàng)目應(yīng)用中,有時(shí)會(huì)設(shè)計(jì)出這樣的一種數(shù)據(jù)表,每個(gè)時(shí)間段產(chǎn)生一個(gè)新表,例如是按年或月或日。相同類型的表中,所有的字段結(jié)構(gòu)都是一樣的。而 Hibernate 提供的類與表的映射,是只能映射到一個(gè)具體表的,在程序的運(yùn)行過(guò)程中,很難去動(dòng)態(tài)修改一個(gè) hbm 對(duì)應(yīng)的表名。我在網(wǎng)上也有看到一實(shí)現(xiàn),但是很復(fù)雜,并且不符合我的要求。

創(chuàng)新互聯(lián)是一家從事企業(yè)網(wǎng)站建設(shè)、成都網(wǎng)站設(shè)計(jì)、網(wǎng)站制作、行業(yè)門戶網(wǎng)站建設(shè)、網(wǎng)頁(yè)設(shè)計(jì)制作的專業(yè)網(wǎng)絡(luò)公司,擁有經(jīng)驗(yàn)豐富的網(wǎng)站建設(shè)工程師和網(wǎng)頁(yè)設(shè)計(jì)人員,具備各種規(guī)模與類型網(wǎng)站建設(shè)的實(shí)力,在網(wǎng)站建設(shè)領(lǐng)域樹立了自己獨(dú)特的設(shè)計(jì)風(fēng)格。自公司成立以來(lái)曾獨(dú)立設(shè)計(jì)制作的站點(diǎn)近千家。
因此我就想到直接用 jdbc 去操作數(shù)據(jù)庫(kù),這樣的做法是繞過(guò) Hibernate 了。方法是從 Hibernate 的 session 中,直接取得數(shù)據(jù)庫(kù) connection ,然后就直接 jdbc 了。
后來(lái)在升級(jí)了 proxool 到 9.0RC3 后,發(fā)現(xiàn)居然出現(xiàn)了數(shù)據(jù)庫(kù)連接無(wú)法釋放的問(wèn)題。為了解決這個(gè)問(wèn)題,我查閱了 Hibernate doc。我發(fā)現(xiàn)原來(lái)用Hibernate SQLQuery 可以更好的解決,并且可以重新用于 Hibernate hbm 機(jī)制。以下舉例說(shuō)明。
例如我有一個(gè) pojo 是 ReadInfo,用來(lái)記錄閱讀信息的。由于數(shù)據(jù)量寵大,所以我的思路是按月劃分,每個(gè)月一張表。所以只是表名不同,而字段是完全相同的。
ReadInfo.java 是這樣的,其中 userId, year, month, day 是聯(lián)合主鍵:
private Integer userId;
private Integer year;
private Integer month;
private Integer day;
private Integer point ;
那么相應(yīng)的 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 個(gè)細(xì)節(jié)
1. pojo 所映射的 table tblReadInfo 實(shí)際上是不存在的。實(shí)際的表是 tblRead200710 之類的;
2. mutable 要設(shè)置為 false,即是說(shuō),關(guān)閉 Hibernate 對(duì)這個(gè) pojo 的任何持久化操作,以避免 Hibernate 把數(shù)據(jù)寫到 tblReadInfo 中(這個(gè)表是不存在的嘛)。因此,所有的持久化操作,都是需要自己通過(guò)Hibernate SQLQuery 來(lái)處理。
現(xiàn)在可以看一下 ado 中的操作了,先看一個(gè) 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;
- }
上面的代碼,關(guān)鍵是以下幾點(diǎn):
1. 通過(guò)函數(shù)參數(shù)的 year, month 來(lái)確定要操作的表名,我自己寫了一個(gè) Misc.formatMoon(year, month) 來(lái)生成 "yyyyMM" 格式的字串;
2. 使用了 SQLQuery ,再通過(guò) query.addEntity(ReadInfo.class); 建立與 ReadInfo 的映射關(guān)系;
3. query.setXxx() 與 PreparedStatement 的類似,不過(guò)索引是從 0 開(kāi)始;
4. 其它的就跟一般的 Query 操作類似的了。
再看一個(gè) 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 等操作也是這樣通過(guò)Hibernate SQLquery來(lái)實(shí)現(xiàn)的。
這種Hibernate SQLquery處理方式的麻煩的地方是需要手工寫 SQL,因此要盡量寫通用的標(biāo)準(zhǔn)SQL,不然在數(shù)據(jù)庫(kù)兼容方面會(huì)有問(wèn)題。當(dāng)然,有時(shí)是會(huì)出現(xiàn)無(wú)法兼容的情況,那么可以考慮把 SQL寫到配置文件中,根據(jù)不同的數(shù)據(jù)庫(kù),裝載相應(yīng)的配置文件。
【編輯推薦】
- Hibernate更新出錯(cuò)的解決
- 深入淺出Hibernate學(xué)習(xí)筆記 Criteria Query
- 正確理解Hibernate Inverse
- 對(duì)Hibernate緩存機(jī)制的分析
- Hibernate HQL查詢解析
當(dāng)前名稱:使用Hibernate SQLquery實(shí)現(xiàn)動(dòng)態(tài)表
本文URL:http://fisionsoft.com.cn/article/djooojg.html


咨詢
建站咨詢
