从实例看hibernate的主键生成策略

学习了hibernate会发现,hibernate中有实体类,实体类的映射文件,但是我们怎么样才能知道实体类的主键是怎样的生成方式呢?hibernate提供的主键生成策略帮我们完美地解答了这个疑问。下面让我们一起从实例开始认识hibernate的实体生成策略。

一、首先通过User实体类和映射文件的实例

User的实体类

package com.bjpowernode.hibernate;

import java.util.Set;

public class User {
	
	private int id;
	
	private String name;

	private Set roles;
	
	public int getId() {
		return id;
	}

	public void setId(int id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

	public void setName(String name) {
		this.name = name;
	}

	public Set getRoles() {
		return roles;
	}

	public void setRoles(Set roles) {
		this.roles = roles;
	}
}

映射文件:User.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC 
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
	<class name="com.bjpowernode.hibernate.User" table="t_user">
		<id name="id">   /*表示id是主键,且使用的策略是native*/
			<generator class="native"/>
		</id>
		<property name="name"/>
		<set name="roles" table="t_user_role">
			<key column="user_id" not-null="true"/>
			<many-to-many class="com.bjpowernode.hibernate.Role" column="role_id" />	
		</set>
	</class>
</hibernate-mapping>

二、hibernate主键生成策略解析 

对于主键生成策略,针对我的理解,主要将它分为自增长型、保证唯一性型、手动型、依赖数据库型四类。

1.自增长型:  

(1)increment  

a)对主键值采取自动顺序增长的方式生成新的主键,值默认从1开始。  

b)原理:在当前应用实例中维持一个变量,以保存当前最大值,之后每次需要生成主键值的时候将此值加1作为主键.不依赖于底层的数据库,因此所有的数据库都可以使用  

c)缺点:通过increment的生成主键的原理可推断,此种主键生成策略不适用于集群、同一时段大量用户并发访问的系统,既当大量用户同一时间段同时进行插入操作的时候,可能存在取得相同的最大值然后再同时+1的情况,这个时候就会造成主键冲突。因此,如果同一数据库有多个实例访问,此方式必须避免使用。 

(2)identity  

a)根据底层数据库,来支持自动增长,不同的数据库用不同的主键增长方式。  

b)特点: 与底层数据库有关,要求数据库支持Identity,如MySQl中是auto_increment, SQL Server 中是Identity。支持的数据库有MySql、SQL Server、DB2、Sybase和HypersonicSQL。  

c)好处:在建表的时候指定了id为自动增长,实际开发中就不需要自己定义插入数据库的主键值,系统会自动顺序递增一个值 。Identity无需Hibernate和用户的干涉,使用较为方便,但由于依赖于数据库,所以不便于在不同的数据库之间移植程序。  

2.保证“唯一性”型 

(1)UUID  

a)原理UUID使用128位UUID算法生成主键,能够保证网络环境下的主键唯一性,也就能够保证在不同数据库及不同服务器下主键的唯一性。所以使用于所有数据库。  

b)特点;能够保证数据库中的主键唯一性,但是在生成的主键占用比较多的存贮空间 

(2)Hilo  

a)原理:通过hi/lo 算法(Hilo使用高低位算法生成主键,高低位算法使用一个高位值和一个低位值,然后把算法得到的两个值拼接起来)实现的主键生成机制,需要额外的数据库表保存主键生成历史状态。  

b)特点:需要额外的数据库表和字段提供高位值来源。默认情况下使用的表是 hibernate_unique_key,默认字段叫作next_hi。next_hi必须有一条记录否则会出现错误。需要额外的数据库表的支持,能保证同一个数据库中主键的唯一性,但不能保证多个数据库之间主键的唯一性。Hilo主键生成方式由Hibernate 维护,所以Hilo方式与底层数据库无关。 

3.依赖数据库型:  

【PS:UUID,increment、Hilo、assigned:对数据库无依赖】  

(1)sequence 

sequence实际是就是一张单行单列的表。 

(2)native  

a)作用:根据数据库的类型,自动在sequence 、identity和,hilo进行切换。  

b)实现自动切换的依据:根据Hibernate配置文件中的方言来判断是Oracle还是Mysql、SqlServer,然后针对数据库的类型抉择 sequence还是identity作为主键生成策略。  

c)用处:由于Hibernate会根据底层数据库采用不同的映射方式,因此灵活性高,便于程序移植,项目中如果用到多个数据库时,可以使用这种方式。 

(3)foreign 

只适用基于共享主键的一对一关联映射的时候使用。即一个对象的主键是参照的另一张表的主键生成的。

4.手动型(唯一一个)  

(1)assigned  

a)作用:用于手工分配主键生成器,一旦指定为这个了,Hibernate就不在自动为程序做主键生成器了。没有指定<generator>标签时,默认就是assigned主键的生成方式  

b)使用方法:在程序中session.save();之前,由程序员自己指定主键值为多少。例如:user.setId(1);这就是在程序中程序员手动为用户表指定主键值为1。  

三、总结:

一般来说推荐UUID,因为生成主键唯一,且对数据库无依赖,可移植性强。由于常用的数据库,如Oracle、DB2、SQLServer、MySql 等,都提供了易用的主键生成机制(Auto-Increase 字段或者Sequence)。我们可以在数据库提供的主键生成机制上,采用native,sequence或者identity的主键生成方式。 

 

不过值得注意的是,一些数据库提供的主键生成机制在效率上未必最佳大量并发insert数据时可能会引起表之间的互锁。因此,对于并发Insert要求较高的系统,推荐采用uuid作为主键生成机制。

 

总之,hibernate主键生成器选择,还要具体情况具体分析**。一般而言,利用uuid方式生成主键将提供最好的性能和数据库平台适应性。


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值