Hibernate几种常用主键生成策略

    上一篇讲了Hibernate矿建的一些基础知识,其中讲到了主键生成策略,都知道,Hibernate提供相应的API能自动生成数据库表,说到表,一定会设计到的一个概念就是主键,主键是由程序自动生成的,不应该由用户自己输入,那么Hibernate在往表中填充数据库时,主键是怎么生成的那,Hibernat提供了主键生成策略,下面主要讲一下常用的几种,配置形式如下:

<id name="id">
    <generator class="主键生成策略名称" />      
</id>

uuid

      Universally Unique Identifier的缩写,通用唯一识别码,UUID是由一组32位数的16进制数字所构成是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的; Hibernate在保存对象时,生成一个uuid字符串作为主键,保证了唯一性,但其无任何业务逻辑意义; 适用与所有的数据库,但是生成的主键占用的存储空间较大


identity

      identity是由底层数据库自己生成的标识符,但这个主键必须设置为自增长,由数据库生成,使用identity的前提条件是底层数据库支持自动增长字段类型,如SQL Server、MySQL等,Oracle这类没有自增字段的则不支持。如果使用MySQL数据库,则主键字段必须设置成auto_increment(此句上网查得的),但是自己试验得出,Hibernate在创建MySql中的表时会自动将该字段设置成auto_increment,该字段必须设置为是能自增的数据类型,否则会报错:ERROR SchemaExport:274 - Unsuccessful: create table User (id varchar(255) not null auto_increment


hilo

      hilo(高低位方式high low)是hibernate中最常用的一种生成方式,需要一张额外的表保存hi的值,该表中只有一条数据,即记录hi的下一个值,适用于所有数据库,但生成的标志只能在一个数据库中保证唯一,配置如下:

<id name="id" column="id">
    <generator class="hilo">
        <!--指定保存hi值的表名,MySQL默认表名为hibernate_unique_key-->
        <param name="table">hibernate_hilo</param>
        <!--指定保存hi值的列名-->
        <param name="column">next_hi</param>
        <!--指定低位的最大值-->
        <param name="max_lo">100</param>
    </generator>
</id>

如果使用默认的表名和列名,可以省略table和column:

<id name="id" column="id">
    <generator class="hilo">
        <param name="max_lo">100</param>
    </generator>
</id>

hilo生成器生成主键的过程(以hibernate_unique_key表,next_hi列为例):

  1. 获得hi值:读取并记录数据库的hibernate_unique_key表中next_hi字段的值,数据库中此字段值加1保存。

  2. 获得lo值:从0到max_lo循环取值,差值为1,当值为max_lo值时,重新获取hi值,然后lo值继续从0到max_lo循环。

  3. 根据公式 hi * (max_lo + 1) + lo计算生成主键值。

注意:当hi值是0的时候,那么第一个值不是0*(max_lo+1)+0=0,而是lo跳过0从1开始,然后再按上面的规律生成主键,即1,101,202。。。依次产生,知道地位到达最大值

那max_lo配置多大合适呢?
      这要根据具体情况而定,如果系统一般不重启,而且需要用此表建立大量的主键,可以吧max_lo配置大一点,这样可以减少读取数据表的次数,提高效率;反之,如果服务器经常重启,可以吧max_lo配置小一点,可以避免每次重启主键之间的间隔太大,造成主键值主键不连贯。网上查的说:只需要当lo值循环了一次之后,才需要更新数据库一次,其他的操作全部是在内存中完成,避免了每次生成主键都得操作数据库,效率较高,但是我每操作一个,查一下hi的值,该值都会变的,此处还没搞懂???


sequence

只适用于支持sequence机制生成主键的数据库,主键值由数据库生成,如MySql就不支持,Oracle就支持


native

      native由hibernate根据使用的数据库自行判断采用identity、hilo、sequence其中一种作为主键生成方式,灵活性很强,这样以来如果一个项目中使用多个数据库时,就可以使用这种方式


foreign

      使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中

<id name="id">
    <generator class="foreign">
        <param name="property">idCard</param>
    </generator>
</id>       
<!--当前主键参照了对端的主键idCard,true决定**重点内容**-->
<one-to-one name="idCard" constrained="true" />


对数据库的依赖性

  • UUID,increment、Hilo、assigned:对数据库无依赖
  • identity:依赖Mysql或sql server,主键值不由hibernate维护
  • sequence:适合于oracle等支持序列的dbms,主键值不由hibernate维护,由序列产生
  • native:根据底层数据库的具体特性选择适合的主键生成策略,如果是mysql或sqlserver,选择identity,如果是oracle,选择sequence


主键生成策略的选择

      一般来说推荐UUID,因为生成主键唯一,且对数据库无依赖,可移植性强


主键的分类

  • 自然主键:建表的时候,使用对象中本身的属性作为表的主键。
  • 代理主键:没有使用对象中的自身的属性作为表中的主键,使用和对象不相关的属性作为主键。

注:在建表的时候,建议使用代理主键,自然主键有可能会参与到业务逻辑中,有可能出现重复或者有的时候需要修改,主键不能修改,因此自然主键就不能使用了。

猜你喜欢

转载自blog.csdn.net/wrs120/article/details/79446601