Hibernate采用对象标识符,也就是通常我们所说的OID来创建对象和数据库表里记录的对应关系,对象的OID和表里的主键对应,所以说OID是非常重要的,不应该让程序来给它赋值.数据库区分同一表的不同记录是用主键来区分.数据库中的主键最重要的3个基本要素就是不允许为null,不允许有重复值,主键永远不会改变.所以通常我们设计表都会设计主键的值为自动增加,没有业务逻辑含义的一组数字,当然针对每个数据库,设置的方法也不同.但是都非常简单.加一个属性就可以了.
而JAVA区分同一类的不同对象是用内存地址,在JAVA语言中判断两个对象的引用变量是否想相等,有以下两种比较方式.1)用运算符"=="比较内存地址,此外还可以用Object的equals方法也是按内存地址比较.2)比较两个对象的值是否相同,JAVA中的一些覆盖了Object类的equals方法实现比较合适.例如String和Date类,还有JAVA包装类.如果是String.equals(String)这种方式的比较就是比较这两个String的值的.如果是Object原是的equals方法就是比较地址了.这点很容易混淆.
通常,为了包装Hibernate的OID的唯一性和不可变性,由Hibernate或者底层数据库来给OID赋值比较合理.因此我们在编程的时候最好把持久化类的OID设置为private或者protected类型,这样可以防止JAVA程序随便更改OID.而OID的get方法我们还是要设置为public类型,这样方便我们读取. 在对象-关系映射文件里的<id元素是用来设置对象标识符OID的.type通常设置为long.而<generator子元素用来设置OID的标识符生成器,Hibernate提供了标识符生成器的接口net.sf.hibernate.id.IdentifierGenerator接口,并且提供了N多中内置的实现,和对应的缩写.我们只要把这些实现类的类名或者所写设置在<generator子元素的class属性中,就能完成OID的配置了.具体的内置标识符生成器如下:
1)increment 代理主键,hibernate自动以递增的方式来生成标识符,每次增加1.
2)identity 代理主键,由底层数据库生成标识符,前提就是底层的数据库支持自动增长的类型.
3)sequence 代理主键,hibernate根据底层数据库生成的标识符,前提是底层数据库支持序列
4)hilo 代理主键,hibernate根据higg/low算法来生成的标识符,把特定表的字段作为high的值,默认选用hibernate_unique_key表的next_hi字段
5)native 代理主键,根据底层数据库对自动生成标识符的支持能力,还选择identity,sequence,或hilo.
6)uuid.hex 代理主键,hibernate采用128位的UUID算法生成标识符,UUID算法能够在网络环境下生成唯一字符串标识符.不过字符串要比数据占用的空间多的多.所以不流行使用.
7)assigned 适用于自然主键,由JAVA应用程序负责生成标识符,为了能让JAVA设置OID.不能吧setId方法设置为非公共类型了,这种方式也尽量避免使用.
这里个人觉得第一种方式,也就是说由Hibernate来生成对象标识符的方式比较好.但是这种方式的缺点是只能一个Hibernate对应一个数据库的表.当同时创建了SeesionFactory实例的时候.两个或者更多的Hibernate对应同一个数据库的时候就会插入出错.这个时候我们可以选择第二种方式把标识符的生成工作交给底层数据库.还有一个小知识点要注意就是OID必须定义为long,int,short类型,如果定义为byte会报异常,这里推荐用long.
总结一下,这7中生成OID标识符的方法,increment 比较常用,把标识符生成的权力交给Hibernate处理.但是当同时多个Hibernate应用操作同一个数据库,甚至同一张表的时候.就推荐使用identity 依赖底层数据库实现,但是数据库必须支持自动增长,sequence 以来底层数据库实现,但是数据库必须支持系列.hilo 根据特定的表实现.这三种方式了.当然针对不同的数据库选择不同的方法.如果你不能确定你使用的数据库具体支持什么的情况下.可以选择第三种.或者用native 让Hibernate来帮选择identity,sequence,或hilo.后边的自然主键不推荐使用,因为自然主键就是具有业务含义的主键,在现在的软件开发结构中,已经很少有人用了.下面总结一下几种常用数据库,可以使用的标识符类型.
MySQL:identity数据库底层实现,需要支持自动增长,increment由Hibernate实现,hilo用特定的表实现,
MSSQL:identity数据库底层实现,需要支持自动增长,increment由Hibernate实现,hilo用特定的表实现,
Oracle:sequence数据库底层实现,需要支持序列,increment由Hibernate实现,hilo用特定的表实现,
以上不难发现,所有的数据库都支持Hibernate用increment实现OID的生成,MYSQL和MSSQL数据库底层实现支持自动增长,而Oracle支持序列,还有用特殊表的实现方式这三个数据库都支持.还有一种实现方式适用于所有的数据库,就是native,由Hibernate去选择使用什么样的方式来生成IOD对象标识符,这种方式也是跨平台的.下面是各种设置方式的例子*.hbm.xml文件四个.例题来源孙MM的<<精通Hibernate>>一书.我非常喜欢这本书,讲的非常简单明了.感兴趣的朋友可以去买一本看看(当当打7.3折哦).
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.HiloTester" table="HILO_TESTER">
<id name="id" type="long" column="ID">
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>
<property name="name" type="string" >
<column name="name" length="15" />
</property>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.IdentityTester" table="IDENTITY_TESTER">
<id name="id" type="long" column="ID">
<generator class="identity"/>
</id>
<property name="name" type="string" >
<column name="name" length="15"/>
</property>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.NativeTester" table="NATIVE_TESTER" >
<id name="id" type="long" column="ID">
<generator class="native"/>
</id>
<property name="name" type="string" >
<column name="name" length="15" />
</property>
</class>
</hibernate-mapping>
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping
PUBLIC "-//Hibernate/Hibernate Mapping DTD 2.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd">
<hibernate-mapping>
<class name="mypack.IncrementTester" table="INCREMENT_TESTER" >
<id name="id" type="long" column="ID">
<meta attribute="scope-set">private</meta>
<generator class="increment"/>
</id>
<property name="name" type="string" >
<column name="NAME" length="15" />
</property>
</class>
</hibernate-mapping>
posted on 2007-05-22 15:05
我心依旧 阅读(3607)
评论(1) 编辑 收藏