参考文献:
http://blog.csdn.net/wanghuan203/article/details/7562395
http://www.cnblogs.com/hoobey/p/5508992.html
声明:主键生成配置直接摘抄了http://www.cnblogs.com/hoobey/p/5508992.html这篇博客的Hibernate各种主键生成策略与配置详解,主要是人家总结的太详细了,我就直接用了,特此感谢。
hibernate提供的主键生成策略,使我们可以在实体类的映射xml文件中设定关键字来告诉hibernate我们要使用的主键生成方式,然后hibernate会根据设定完成数据库的主键控制。
一、实体映射文件(*.hbm.xml)中对id生成策略配置格式
1:user的实体类user.java
package com.entity.hibernate;
public class User {
private int id;
private String name;
public User(){}
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;
}
}
2:user对应的映射文件user.hbm.xml
主键生成配置
二、主键生成配置
1:assigned
主键由外部程序负责生成,在 save() 之前必须指定一个。Hibernate不负责维护主键生成。与Hibernate和底层数据库都无关,可以跨数据库。在存储对象前,必须要使用主键的setter方法给主键赋值,至于这个值怎么生成,完全由自己决定,这种方法应该尽量避免。
特点:可以跨数据库,人为控制主键生成,应尽量避免。
2:increment
由Hibernate从数据库中取出主键的最大值(每个session只取1次),以该值为基础,每次增量为1,在内存中生成主键,不依赖于底层的数据库,因此可以跨数据库。
Hibernate调用org.hibernate.id.IncrementGenerator类里面的generate()方法,使用select max(idColumnName) from tableName语句获取主键最大值。该方法被声明成了synchronized,所以在一个独立的Java虚拟机内部是没有问题的,然而,在多个JVM同时并发访问数据库select max时就可能取出相同的值,再insert就会发生Dumplicate entry的错误。所以只能有一个Hibernate应用进程访问数据库,否则就可能产生主键冲突,所以不适合多进程并发更新数据库,适合单一进程访问数据库,不能用于群集环境。
hibernate_hilo
next_hi
100
hibernate_hilo 指定保存hi值的表名
next_hi 指定保存hi值的列名
100 指定低位的最大值
也可以省略table和column配置,其默认的表为hibernate_unique_key,列为next_hi
100
hilo生成器生成主键的过程(以hibernate_unique_key表,next_hi列为例):
hibernate_seq
100
特点:与hilo类似,只能在支持序列的数据库中使用。
5:sequence
采用数据库提供的sequence机制生成主键,需要数据库支持sequence。如oralce、DB、SAP DB、PostgerSQL、McKoi中的sequence。MySQL这种不支持sequence的数据库则不行(可以使用identity)。
hibernate_id
hibernate_id 指定sequence的名称
Hibernate生成主键时,查找sequence并赋给主键值,主键值由数据库生成,Hibernate不负责维护,使用时必须先创建一个sequence,如果不指定sequence名称,则使用Hibernate默认的sequence,名称为hibernate_sequence,前提要在数据库中创建该sequence。
6:identity
identity由底层数据库生成标识符。identity是由数据库自己生成的,但这个主键必须设置为自增长,使用identity的前提条件是底层数据库支持自动增长字段类型,如DB2、SQL Server、MySQL、Sybase和HypersonicSQL等,Oracle这类没有自增字段的则不支持。
例:如果使用MySQL数据库,则主键字段必须设置成auto_increment。
例如MySQL使用identity,Oracle使用sequence
Hibernate在保存对象时,生成一个UUID字符串作为主键,保证了唯一性,但其并无任何业务逻辑意义,只能作为主键,唯一缺点长度较大,32位(Hibernate将UUID中间的“-”删除了)的字符串,占用存储空间大,但是有两个很重要的优点,Hibernate在维护主键时,不用去数据库查询,从而提高效率,而且它是跨数据库的,以后切换数据库极其方便。
Hibernate在维护主键时,先查询数据库,获得一个uuid字符串,该字符串就是主键值,该值唯一,缺点长度较大,支持数据库有限,优点同uuid,跨数据库,但是仍然需要访问数据库。
10:foreign
使用另外一个相关联的对象的主键作为该对象主键。主要用于一对一关系中。
user
该例使用domain.User的主键作为本类映射的主键。
三、其他注解方式配置
注:“ud”是自定义的策略名,自定义起名
注释方式与配置文件底层实现方式相同,只是配置的方式换成了注释方式
自动增长,适用于支持自增字段的数据库
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
根据底层数据库自动选择方式,需要底层数据库的设置
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
使用表存储生成的主键,可以跨数据库。
@Id
@GeneratedValue(strategy = GenerationType.TABLE, generator = "ud")
@TableGenerator(name = "ud",
table = "hibernate_table",
pkColumnName = "gen_pk",
pkColumnValue = "2",
valueColumnName = "gen_val",
initialValue = 2,
allocationSize = 5)
使用序列存储主键值
@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "ud")
@SequenceGenerator(name = "ud",
sequenceName = "hibernate_seq",
allocationSize = 1,
initialValue = 2)