java

位置:IT落伍者 >> java >> 浏览文章

Hibernate主键生成策略


发布日期:2020年10月31日
 
Hibernate主键生成策略

自动增长identity

适用于MySQLDBMS SQL Server采用数据库生成的主键用于为longshortint类型生成唯一标识

使用SQL Server 和 MySQL 的自增字段这个方法不能放到 Oracle 中Oracle 不支持自增字段要设定sequence(MySQL 和 SQL Server 中很常用)

数据库中的语法如下

MySQLcreate table t_user(id int auto_increment primary key name varchar());

SQL Servercreate table t_user(id int identity() primary key name varchar());

<id name=id column=id type=long>

<generator class=identity />

</id>

sequence

DBOracle均支持的序列用于为longshort或int生成唯一标识

数据库中的语法如下

Oraclecreate sequence seq_name increment by start with ;

需要主键值时可以调用seq_namenextval或者seq_namecurval得到数据库会帮助我们维护这个sequence序列保证每次取到的值唯一

insert into tbl_name(id name) values(seq_namenextval Jimliu);

<id name=id column=id type=long>

<generator class=sequence>

<param name=sequence>seq_name</param>

</generator>

</id>

如果我们没有指定sequence参数则Hibernate会访问一个默认的sequence是hibernate_sequence我们也需要在数据库中建立这个sequence

此外sequence还可以有另外一个参数是paramters可以查看Hibernate的API了解它的用法见orghibernateidSequenceGenerator

调用数据库的sequence来生成主键要设定序列名不然hibernate无法找到

<param name=sequence>NAME_SEQ</param>(Oracle中很常用)

hilo

使用一个高/低位算法生成的longshort或int类型的标识符给定一个表和字段作为高位值的来源默认的表是hibernate_unique_key默认的字段是next_hi它将id的产生源分成两部分DB+内存然后按照算法结合在一起产生id值可以在很少的连接次数内产生多条记录提高效率

MySQLcreate table hi_value(next_hi integer not null);

insert into hi_value(next_hi) values();

<id name=id column=id>

<generator class=hilo>

<param name=table>hi_value</param>

<param name=column>next_hi</param>

<param name=max_lo></param>

</generator>

</id>

在hibernate持久化的时候由hibernate负责生成低位值hilo标识符生成器在生成标识符时需要从hi_value表中取出next_hi的当前值然后修改该值这个操作是在单独的事务中完成的最大的低值在属性max_lo中配置但在Hibernate内存中生成的低位值超过此值时就有需要到数据库的hi_value表中再次读取高位值了

使用hilo生成策略要在数据库中建立一张额外的表默认表名为hibernate_unique_key默认字段为integer类型名称是next_hi(比较少用)

我们也可以自己设置自定义的表名和字段名

<id name=id type=integer>

<column name=id/>

<generator class=hilo>

<param name=my_unique_key/>

<param column=next_hi/>

</generator>

</id>

native

会根据底层数据库的能力从identitysequencehilo中选择一个灵活性更强但此时如果选择sequence或者hilo则所有的表的主键都会从Hibernate默认的sequence或者hilo表中取并且有的数据库对于默认情况主键生成测试的支持效率并不是很高

对于 oracle 采用 Sequence 方式对于MySQL 和 SQL Server 采用identity(自增主键生成机制)native就是将主键的生成工作交由数据库完成hibernate不管(很常用)

<id name=id column=id>

<generator class=native />

</id>

seqhilo

sequence和hilo的结合hilo的高位由sequence产生所以也需要底层数据库的支持

通过hilo算法实现但是主键历史保存在Sequence中适用于支持 Sequence 的数据库如 Oracle(比较少用)

<id name=id column=id>

<generator class=seqhilo>

<param name=sequence>seq_name</param>

<param name=max_lo></param>

</generator>

</id>

increment

这个是由Hibernate在内存中生成主键每次增量为不依赖于底层的数据库因此所有的数据库都可以使用但问题也随之而来由于是Hibernate生成的所以只

能有一个Hibernate应用进程访问数据库否则就会产生主键沖突不能在集群情况下使用

插入数据的时候hibernate会给主键添加一个自增的主键但是一个hibernate实例就维护一个计数器所以在多个实例运行的时候不能使用这个方法

<id name=id column=id>

<generator class=increment />

</id>

uuidhex

使用一个bit的UUID算法生成字符串类型的标识符UUID被编码成一个进制数字的字符串UUID包含IP地址JVM启动时间系统时间(精确到/秒)和一个计数器值(JVM中唯一)

hibernate会算出一个位的唯一值插入

<id name=id column=id>

<generator class=uuidhex />

</id>

uuidstring

hibernate会算出一个位的值插入

assigned

由应用程序负责生成主键标识符往往使用在数据库中没有代理主键使用的主键与业务相关的情况

<id name=id column=id type=string>

<generator class=assigned />

</id>

这种主键的生成方式不建议使用在数据库表设计时就应该使用代理主键(surrogate key)不应使用自然主键(natural key具有业务含义)在没有指定<generator>标签时默认就是assigned主键的生成方式

在插入数据的时候主键由用户自己添加hibernate也不管

foreign

使用外部表的字段作为主键

select

使用触发器生成主键(主要用于早期的数据库主键生成机制少用)

ps:

代理主键是指与业务无关且能唯一标识数据库中记录一般是数据库自动生成的比如mysql可以使用auto_incrementSql可以使用identity生成方式oracle可以使用sequence生成方式自然主键指业务相关由用户指定且能唯一标识数据库中的任意一条记录

简介版

increment代理主键适合于所有数据库由hibernate维护主键自增和底层数据库无关但是不适合于个或以上hibernate进程

identity代理主键适合于Mysql或ms sql server等支持自增的dbms主键值不由hibernate维护

sequence代理主键适合于oracle等支持序列的dbms主键值不由hibernate维护由序列产生

native代理主键根据底层数据库的具体特性选择适合的主键生成策略如果是mysql或sqlserver选择identity如果是oracle选择sequence

hilo代理主键hibernate把特定表的字段作为hign值生成主键值

uuidhex代理主键hibernate采用uuid 位算法生成基于字符串的主键值

assign适合于应用程序维护的自然主键

上一篇:Spring MVC与struts比较

下一篇:Hibernate的HQL多表联合查询使用left join方式