关于unsaved-value 的再问。

转载 2004年07月16日 10:18:00

ywang的提问:

unsaved-value是表示一个对象是新的还是旧的,如果unsaved-value=none 那么就是新的,就会被insert到数据库中,如果unsaved-value=any 就是说明对象是从数据库中load的,被update到数据库中。

我的问题是:unsaved-value是由我们来强制说明这个对象是新的还是旧的,那如果我把一个对象的unsaved-value设置为any,那我要new 一个对象,把他save到数据库中,怎么做呢?我感觉这不是矛盾了吗?主要是我们在写配置文件的时候怎么能说一个对象就一定是new的还是load的?

我查过过去的一些帖子,都是讲到unsaved-value是什么表示什么意思,我还不是不懂,希望大家教我。

robbin的回答:

当你显式的使用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-null="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。

因此,如果你在系统设计的时候,遵循如下原则:

[color=red]1、使用Hibernate的id generator来生成无业务意义的主键,不使用有业务含义的字段做主键,不使用assigned。

2、使用对象类型(String/Integer/Long/...)来做主键,而不使用基础类型(int/long/...)做主键

3、不使用composite-id来处理复合主键的情况,而使用UserType来处理该种情况。[/color]

那么你永远用的是unsaved-value="null" ,不可能用到any/none/..了。

关于unsaved-value 的再问

关于unsaved-value 的再问。作者:robbin (MSN:robbin_fan AT hotmail DOT com)版权声明:本文严禁转载,如有转载请求,请和作者联系ywang的提问:u...
  • lwqadmin
  • lwqadmin
  • 2004年10月27日 14:01
  • 571

saveorUpdate与unsaved-value

  • JAVAZHICHIZHE
  • JAVAZHICHIZHE
  • 2009年09月05日 20:52
  • 2067

Hibernate unsaved-value 属性

Session的saveOrUpdate方法是由Hibernate来判断被操作对象究竟是一个持久化对象还是临时自由状态对象。这需要在对象映射文件的主键id中定义unsaved-value属性,如果不显...
  • tianlincao
  • tianlincao
  • 2010年11月27日 22:18
  • 6146

关于unsaved-value

ywang的提问:unsaved-value是表示一个对象是新的还是旧的,如果unsaved-value=none 那么就是新的,就会被insert到数据库中,如果unsaved-value=any ...
  • neujyj
  • neujyj
  • 2005年02月25日 10:40
  • 581

Hibernate unsaved-value配置

当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value的。某 些情况下(父子表关联保存),当你在程序中并没有显式的...
  • tyb1222
  • tyb1222
  • 2010年09月22日 15:57
  • 1152

unsaved-value的经典解释

     当你显式的使用session.save()或者session.update()操作一个对象的时候,实际上是用不到unsaved-value的。某些情况下(父子表关联保存),当你在程序中并没有...
  • chunkyo
  • chunkyo
  • 2006年04月12日 10:27
  • 3111

hibernate之saveOrUpdate方法以及unsaved-value属性

hibernate之saveOrUpdate方法以及unsaved-value属性
  • fhd001
  • fhd001
  • 2011年03月10日 10:47
  • 1135

关于unsaved-value

    unsaved-value是表示一个对象是新的还是旧的,如果unsaved-value=none 那么就是新的,就会被insert到数据库中,如果unsaved-value=any 就是说明对...
  • szuosky
  • szuosky
  • 2009年02月17日 19:45
  • 191

String/StringBuffer/StringBuilder的区别

首先最大的区别是String是不可变的,而StringBuffer和StringBuilder是可变的 可以在源码中看到,String类是被定义为final的,而StringBuffer和Strin...
  • martinmateng
  • martinmateng
  • 2016年03月05日 12:44
  • 504

先百度再提问,是一种态度

粗看着标题,很多人会以为是标题党,其实今天要和大家聊的话题,还是和这个有很大关系的,《QQ群聊天技巧》谈这个话题真的是有感而发,建过群的朋友,估计很多都有这个经历,很多的朋友问问题,群里没有人回答,就...
  • williaa
  • williaa
  • 2014年09月06日 17:07
  • 158
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:关于unsaved-value 的再问。
举报原因:
原因补充:

(最多只允许输入30个字)