J2EE学习笔记
我们的失落……
BlogJava
首页
新随笔
新文章
联系
聚合
管理
posts - 13,comments - 1,trackbacks - 0
<
2009年8月
>
日
一
二
三
四
五
六
26
27
28
29
30
31
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
1
2
3
4
5
常用链接
我的随笔
我的评论
我的参与
最新评论
留言簿
给我留言
查看公开留言
查看私人留言
随笔分类
ajax(1)
hibernate(2)
java(4)
javascript(2)
jQuery(1)
other(1)
servlet/jsp
spring(2)
struts(1)
原创(1)
转载(13)
随笔档案
2010年6月 (1)
2010年5月 (1)
2010年4月 (1)
2010年3月 (2)
2010年2月 (1)
2010年1月 (1)
2009年11月 (1)
2009年9月 (1)
2009年8月 (2)
2009年5月 (1)
2008年10月 (1)
2008年3月 (1)
收藏夹
Struts(5)
搜索
最新评论
1. re: [转]JAVA语言的反射(Reflection)和内省(Introspector)
哈哈,林林,你很行嘛~:)
--leeo
阅读排行榜
1. [转]SecureCRT中文字体解决方案(6032)
2. [转]spring jdbcTemplate使用(2011)
3. [转]用 join 或 CountDownLatch 让主线程等待所有子线程完成(1198)
4. [转]java.math.BigDecimal的用法(1196)
5. [转]Hibernate映射配置文件中id标签的unsaved-value属性详解(938)
评论排行榜
1. [转]JAVA语言的反射(Reflection)和内省(Introspector)(1)
2. [转]用 join 或 CountDownLatch 让主线程等待所有子线程完成(0)
3. [转]jQuery基础---filter()和find()(0)
4. [转]SecureCRT中文字体解决方案(0)
5. [转]Hibernate saveorUpdate与unsaved-value,save,update,delete总结(0)
[转]Hibernate映射配置文件中id标签的unsaved-value属性详解
当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到
unsaved
-
value
的。某些情况下(父子表关联保存),当你在程序中并没有显式的使用save或者update一个持久对象,那么
Hibernate
需要判断被操作的对象究竟是一个已经持久化过的持久对象,是一个尚未被持久化过的内存临时对象。例如:
Session session
=
;
Transaction tx
=
;
Parent parent
=
(Parent); session.load(Parent.
class
, id);;
Child child
=
new
Child();;
child.setParent(parent);;
child.setName(
"
sun
"
);;
parent.addChild(child);;
s.update(parent);;
s.flush();;
tx.commit();;
s.close();;
在上例中,程序并没有显式的session.save(child); 那么
Hibernate
需要知道child究竟是一个临时对象,还是已经在数据库中有的持久对象。如果child是一个新创建的临时对象(本例中就是这种情况),那么
Hibernate
应该自动产生session.save(child)这样的操作,如果child是已经在数据库中有的持久对象,那么
Hibernate
应该自动产生session.update(child)这样的操作。
因此我们需要暗示一下
Hibernate
,究竟child对象应该对它自动save还是update。在上例中,显然我们应该暗示
Hibernate
对child自动save,而不是自动update。那么
Hibernate
如何判断究竟对child是save还是update呢?它会取一下child的主键属性 child.getId() ,这里假设id是 java.lang.Integer类型的。如果取到的Id值和hbm映射文件中指定的unsave-
value
相等,那么
Hibernate
认为child是新的内存临时对象,发送save,如果不相等,那么
Hibernate
认为child是已经持久过的对象,发送update。
unsaved
-
value
="null" (默认情况,适用于大多数对象类型主键 Integer/Long/String/...)
当
Hibernate
取一下child的Id,取出来的是null(在上例中肯定取出来的是null),和
unsaved
-
value
设定值相等,发送save(child)
当
Hibernate
取一下child的id,取出来的不是null,那么和
unsaved
-
value
设定值不相等,发送update(child)
例如下面的情况:
Session session
=
;
Transaction tx
=
;
Parent parent
=
(Parent); session.load(Parent.
class
, id);;
Child child
=
(Child); session.load(Child.
class
, childId);;
child.setParent(parent);;
child.setName(
"
sun
"
);;
parent.addChild(child);;
s.update(parent);;
s.flush();;
tx.commit();;
s.close();;
child已经在数据库中有了,是一个持久化的对象,不是新创建的,因此我们希望
Hibernate
发送update(child),在该例中,
Hibernate
取一下child.getId(),和unsave-
value
指定的null比对一下,发现不相等,那么发送update(child)。
BTW: parent对象不需要操心,因为程序显式的对parent有load操作和update的操作,不需要
Hibernate
自己来判断究竟是save还是update了。我们要注意的只是child对象的操作。另外
unsaved
-
value
是定义在Child类的主键属性中的。
<
class
name
="Child"
table
="child"
>
<
id
column
="id"
name
="id"
type
="integer"
unsaved-value
="null"
>
<
generator
class
="identity"
/>
</
id
>
</
class
>
如果主键属性不是对象型,而是基本类型,如int/long/double/...,那么你需要指定一个数值型的
unsaved
-
value
,例如:
unsaved-value="0"
在此提醒大家,很多人以为对主键属性定义为int/long,比定义为Integer/Long运行效率来得高,认为基本类型不需要进行对象的封装和解构操作,因此喜欢把主键定义为int/long的。但实际上,
Hibernate
内部总是把主键转换为对象型进行操作的,就算你定义为int/long型的,
Hibernate
内部也要进行一次对象构造操作,返回给你的时候,还要进行解构操作,效率可能反而低也说不定。因此大家一定要扭转一个观点,在
Hibernate
中,主键属性定义为基本类型,并不能够比定义为对象型效率来的高,而且也多了很多麻烦,因此建议大家使用对象型的Integer/Long定义主键。
unsaved
-
value
="none"和
unsaved
-
value
="any"
主主要用在主键属性不是通过
Hibernate
生成,而是程序自己setId()的时候。
在这里多说一句,强烈建议使用
Hibernate
的id generator,或者你可以自己扩展
Hibernate
的id generator,特别注意不要使用有实际含义的字段当做主键来用!例如用户类User,很多人喜欢用用户登陆名称做为主键,这是一个很不好的习惯,当用户类和其他实体类有关联关系的时候,万一你需要修改用户登陆名称,一改就需要改好几张表中的数据。偶合性太高,而如果你使用无业务意义的id generator,那么修改用户名称,就只修改user表就行了。
由这个问题引申出来,如果你严格按照这个原则来设计数据库,那么你基本上是用不到手工来setId()的,你用
Hibernate
的id generator就OK了。因此你也不需要了解当
unsaved
-
value
="none"和
unsaved
-
value
="any"
究竟有什么含义了。如果你非要用assigned不可,那么继续解释一下:
unsaved
-
value
="none" 的时候,由于不论主键属性为任何值,都不可能为none,因此
Hibernate
总是对child对象发送update(child)
unsaved
-
value
="any" 的时候,由于不论主键属性为任何值,都肯定为any,因此
Hibernate
总是对child对象发送save(child)
大多数情况下,你可以避免使用assigned,只有当你使用复合主键的时候不得不手工setId(),这时候需要你自己考虑究竟怎么设置
unsaved
-
value
了,根据你自己的需要来定。
BTW: Gavin King强烈不建议使用composite-id,强烈建议使用UserType。
因此,如果你在系统设计的时候,遵循如下原则:
1、使用
Hibernate
的id generator来生成无业务意义的主键,不使用有业务含义的字段做主键,不使用assigned。
2、使用对象类型(String/Integer/Long/...)来做主键,而不使用基础类型(int/long/...)做主键
3、不使用composite-id来处理复合主键的情况,而使用UserType来处理该种情况。
那么你永远用的是
unsaved
-
value
="null" ,不可能用到any/none/..了。
posted on 2009-08-17 22:41
J2EE学习笔记
阅读(938)
评论(0)
编辑
收藏
所属分类:
转载
、
hibernate
新用户注册
刷新评论列表
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
IT新闻
Chat2DB
C++博客
博问
管理
相关文章:
[转]java内部类
[转]在JScript中运算符"||"和"&&"的特殊特性
[转]JavaScript判断变量类型:typeof函数与constructor属性异同
[转]Spring 2.5中JdbcTemplate类query方法的三种回调接口
[转]spring jdbcTemplate使用
[转]JAVA语言的反射(Reflection)和内省(Introspector)
[转]用 join 或 CountDownLatch 让主线程等待所有子线程完成
[转]jQuery基础---filter()和find()
[转]SecureCRT中文字体解决方案
[转]Hibernate saveorUpdate与unsaved-value,save,update,delete总结