快速业务通道

别让Hibernate偷走了你的标识符 - 编程入门网

作者 佚名技术 来源 NET编程 浏览 发布时间 2012-06-21
ckage="my.package"> <class name="Person" table="PERSON"> <id name="id" column="ID" unsaved-value="null"> <generator class="sequence"> <param name="sequence">PERSON_SEQ</param> </generator> </id> <version name="version" column="VERSION" /> <!-- Map Person-specific properties here. --> </class> </hibernate-mapping>

别让Hibernate偷走了你的标识符(2)

时间:2011-01-04

Hibernate映像文件指明了Person的id字段代表了数据库中的ID列(也就是说,它是PERSON表的主键)。包含在id标签中的unsaved-value="null"属性告诉Hibernate使用id字段来判断一个Person对象之前是否被保存过。ORM框架必须依靠这个来判断保存一个对象的时候应该使用SQL的INSERT字句还是UPDATE字句。在这个例子中,Hibernate假定一个新对象的id字段一开始为null值,当它第一次被保存时才id才被赋予一个值。generator标签告诉Hibernate当对象第一次保存时,应该从哪里获得指派的id。在这个例子中,Hibernate使用数据库序列作为产生唯一id的来源。最后,version标签告诉Hibernate使用Person对象的version字段进行并发控制。Hibernate将会执行乐观锁方案(optimistic locking scheme),根据这个方案,Hibernate在保存对象之前会检查对比对象的version值和数据库中相应数据的version值。

我们的Person对象还缺少的是equals()方法和hashCode()方法的实现。既然这是一个持久化对象,我们并不想依赖于这两个方法的缺省实现,因为缺省实现并不能分辨代表数据库中同一实体的不同实例。一种简单而又显然的实现方法是利用id字段来进行equal()方法的比较以及生成hashCode()方法的结果。

public boolean equals(Object o) {   if (this == o) return true;   if (o == null || !(o instanceof Person))    return false;   Person other = (Person)o;   if (id == other.getId()) return true;   if (id == null) return false;   // equivalence by id   return id.equals(other.getId()); } public int hashCode() {   if (id != null) {    return id.hashCode();   }   else {    return super.hashCode();   } }

不走运的是,这个实现存在着问题。当我们首次创建Person对象的时候id的值是null,这意味着任何两个没有被保存的Person对象都将被认为是等价的。如果我们想创建一个Person对象并把它放到Set数据结构中,再创建了一个完全不同的Person对象也把它放到同一个Set里面,事实上第2个Person对象并不能被加入。这是因为Set会断定所有未经保存的对象都是相同的。

你可能会试探着去实现一个只使用被设置过的id的equals()方法。毕竟,如果两个对象都没有被保存过,我们可以假定它们是不同的对象。这是因为在它们被保存到数据库的时候,它们会被赋予不同的主键。

public boolean equals(Object o) {   if (this == o) return true;   if (o == null || !(o instanceof Person)) return false;    Person other = (Person)o;   // unsaved objects are never equal   if (id == null || other.getId() == null) return false;   return id.equals(other.getId()); }

这里有个隐藏的问题。Java的Collection框架在它的生命周期中需要基于不变字段的equals()和hashCode()方法。换句话来说,当一个对象处在Collection中的时候,你不可以改变equals()和hashCode()的返回值。举个例子,下面这段程序:

Person p = new Per

凌众科技专业提供服务器租用、服务器托管、企业邮局、虚拟主机等服务,公司网站:http://www.lingzhong.cn 为了给广大客户了解更多的技术信息,本技术文章收集来源于网络,凌众科技尊重文章作者的版权,如果有涉及你的版权有必要删除你的文章,请和我们联系。以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!

分享到: 更多

Copyright ©1999-2011 厦门凌众科技有限公司 厦门优通互联科技开发有限公司 All rights reserved

地址(ADD):厦门软件园二期望海路63号701E(东南融通旁) 邮编(ZIP):361008

电话:0592-5908028 传真:0592-5908039 咨询信箱:web@lingzhong.cn 咨询OICQ:173723134

《中华人民共和国增值电信业务经营许可证》闽B2-20100024  ICP备案:闽ICP备05037997号