我在实际的项目应用中,有时会设计出这样的一种数据表,每个时间段产生一个新表,例如是按年或月或日。相同类型的表中,所有的字段结构都是一样的。而
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 SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQLQuery 查询Oracle char类型结果为一个字符解决方法 Hibernate SQL...
NULL 博文链接:https://mlxnle.iteye.com/blog/1766676
hibernate sql hqlsql
通过Session接口,我们能够很方便的创建一个SQLQuery(SQLQuery是一个接口,在Hibernate4.2.2之前,默认返回的是SQLQuery的实现类——SQLQueryImpl对象,在下文中出现的SQLQuery如非注明,都是指该子类)对象来进行...
Hibernate+本地SQL查询SQLQuery宣贯.pdf
query.setFirstResult()是数据库SQL语句实现。 2.你说是在数据库就分页好呢?还是把结果集都取到内存再分页好呢?(应该是在数据库就分了好些吧,但是如果在内存分页的话,换页的时候是不是更快一些呢?) 3.在...
fix包 博文链接:https://raymondhekk.iteye.com/blog/250427
Hibernate+本地SQL查询SQLQuery.pdf
Hibernate支持强大且易于使用的面向对象查询语言(HQL)。 如果希望通过编程的方式创建查询,Hibernate提供了完善的按条件(Query By Criteria, QBC)以及按样例(Query By Example, QBE)进行Hibernate查询的功能。 你也...
使用本地sql语句查询后,无需再使用Object对查询结果进行强制转换,而是直接将查询结果放到实体Bean里了。 PS: 其实只有一版,这里只所以叫最终版是因为该附件我上传了好几天传不上去,到最后报告说‘资源已经存在...
HQL(Hibernate Query Language):是面向对象的查询语句,它的语法和SQL语句有些相像,在运行时才得以解析.HQL并不像SQL那样是.
Hibernate中使用Criteria Query各种QBC查询
上传的资料都是非常经典的,这也是我学习过程中的心得,希望大家能给我指点,也希望大家多上传资料共同学习。千万不要传空文件夹。。。那些人很可恶啊
2.通过Hibernate执行SQL 2.1 创建session Configuration config = new Configuration(); config.configure(); SessionFactory sf = config.buildSessionFactory(); Session session = sf.openSession();
Hibernate使用中防止SQL注入的几种方案 Hibernate是一个开放源代码的对象关系映射框架,它对JDBC进行了非常轻量级的对象封装,使得Java程序员可以随心所欲的使用对象编程思维来操纵数据库。 在获取便利操作的同时...
◆使用的SQL语言不同:JDBC使用的是基于关系型数据库的标准SQL语言,Hibernate使用的是HQL(Hibernate query language)语言 ◆操作的对象不同:JDBC操作的是数据,将数据通过SQL语句直接传送到数据库中执行,...
HQL is database independent and translated into SQL by Hibernate at runtime. When writing HQL, we can concentrate on the objects and properties without knowing much detail on the underlying database. ...
16.1. 使用SQLQuery 16.1.1. 标量查询(Scalar queries) 16.1.2. 实体查询(Entity queries) 16.1.3. 处理关联和集合类(Handling associations and collections) 16.1.4. 返回多个实体(Returning multiple ...