别让Hibernate偷走了你的标识符
http://tech.ddvip.com 2006年11月20日 社区交流
本文详细介绍别让Hibernate偷走了你的标识符
对UUID的产生算法有多种实现。既然最终UUID是一种标准格式,我们在IdGenerator类中采用哪一种实现都没有关系。既然无论采用什么算法每个id都会被保证唯一,我们甚至可以在任何时候改变算法的实现或是混合匹配不同的实现。如果你使用的是java1.5或更高版本,最方便的实现是java.util.UUID类。
public class IdGenerator {
public static String createId() {
UUID uuid = java.util.UUID.randomUUID();
return uuid.toString();
}
}对不使用java1.5或更高版本的人来说,至少有两种扩展库实现了UUID并且和1.5之前的java版本兼容: Apache Commons ID project 和 Java UUID Generator(JUG) project.它们都在Apache的旗下。(在LGPL之下JUG也是可用的)
这是使用JUG库实现IdGenerator的例子。
import org.safehaus.uuid.UUIDGenerator;
public class IdGenerator {
public static final UUIDGenerator uuidGen = UUIDGenerator.getInstance();
public static String createId() {
UUID uuid = uuidGen.generateRandomBasedUUID();
return uuid.toString();
}
}Hibernate内置的UUID生成器算法又如何呢?这是一个得到验证对象标识用的UUID的适当途径吗?如果你想让对象标识符独立于对象的持久化,这就不是一个好方法。虽然Hibernate确实提供有让它为你生成UUID的选项,但这样的话我们又回到了那个最早的问题上:对象ID的获得并不在它们被创建的时候,而在它们被保存的时候。
使用UUID作为数据库主键的最大障碍是它们在数据库中(而不是在内存中)的大小,在数据库中索引和外键的复合会促使主键大小的增加。你必须在不同的情况下使用不同的表示方法。使用String表示,数据库的主键大小将会是32或36字节。Id也可以直接使用位存储,这样将减少一半的占用空间,但是如果你直接查询数据库,id将变得难以理解。这些方法对你的工程是否可行取决于你的需求。 如果你的数据库不接受UUID作为主键,你可以考虑使用数据库序列。但总是应该让新对象创建的时候被指派一个ID而不是让Hibernate管理你的ID。在这种情况下,创建新的域对象的商业对象可以调用一个使用data access object(DAO)从数据库序列中获取数据库id的服务。如果你使用一个长整型来表示你的对象id,一个单独的数据库序列(以及服务方法)对你的域对象来说已经足够了。
小结
当对象持久化到数据库中时,对象的标识符总时很难被恰当的实现。尽管如此,问题其实完全是由存在着在保存之前不持有ID的对象的现象衍生而来的。我们可以通过从诸如Hibernate这样的对象—关系映像框架手中取走指派对象ID的职责来解决这个问题。相对的,一旦对象被实例化,它就应该被指派一个ID。这使对象标识符变成简单而不易出错,也减少了领域模型中需要的代码量。
责编:豆豆技术应用