<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 495,comments - 227,trackbacks - 0
    http://callan.javaeye.com/blog/156123

    我在實際的項目應用中,有時會設計出這樣的一種數據表,每個時間段產生一個新表,例如是按年或月或日。相同類型的表中,所有的字段結構都是一樣的。而 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 寫到配置文件中,根據不同的數據庫,裝載相應的配置文件咯。

    posted on 2010-08-25 14:41 SIMONE 閱讀(2657) 評論(1)  編輯  收藏 所屬分類: JAVAJSP

    FeedBack:
    # re: 使用hibernate SQLQuery實現動態表
    2014-03-28 11:21 | hiber
    good  回復  更多評論
      
    主站蜘蛛池模板: 日韩在线免费看网站| 亚洲欧洲国产综合AV无码久久| 在线观看免费为成年视频| 国产拍拍拍无码视频免费| 春暖花开亚洲性无区一区二区 | 亚洲精品国产suv一区88| 亚洲AV第一页国产精品| 亚洲一区二区高清| 成人永久福利免费观看| 青青青免费国产在线视频小草| 久久久久免费精品国产| jyzzjyzz国产免费观看| 看亚洲a级一级毛片| 亚洲综合中文字幕无线码| 夜夜亚洲天天久久| 亚洲成在人线av| 亚洲区小说区图片区QVOD| 亚洲男人在线无码视频| 免费一区二区三区四区五区 | 亚洲av永久无码精品秋霞电影秋| 91亚洲精品麻豆| 亚洲精品乱码久久久久久下载| 亚洲AV永久无码精品一百度影院| 中文字幕人成人乱码亚洲电影| 亚洲精品国产日韩无码AV永久免费网| 国产麻豆剧传媒精品国产免费| 中文字幕无码成人免费视频| 日本三级2019在线观看免费| 色老头永久免费网站| 182tv免费视视频线路一二三| 2019中文字幕免费电影在线播放 | 亚洲va无码专区国产乱码| 亚洲精品午夜无码电影网| 亚洲欧洲∨国产一区二区三区| 国产性爱在线观看亚洲黄色一级片 | 很黄很黄的网站免费的| 无码国产精品一区二区免费虚拟VR| 久久国产免费福利永久| 黄色片在线免费观看| 午夜免费福利在线观看| 国产精品成人免费综合|