温馨提示×

温馨提示×

您好,登录后才能下订单哦!

密码登录×
登录注册×
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》

如何使用Hibernate SQLquery实现动态表

发布时间:2021-07-13 18:39:28 来源:亿速云 阅读:275 作者:chen 栏目:编程语言

这篇文章主要讲解了“如何使用Hibernate SQLquery实现动态表”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何使用Hibernate SQLquery实现动态表”吧!

在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。而 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实现动态表”的内容了,经过本文的学习后,相信大家对如何使用Hibernate SQLquery实现动态表这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!

向AI问一下细节

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

AI