ID生成策略
1.XX.hbm.xml方式
a、常用四个:native identity sequence uuid
Native主键生成方式会根据不同的底层数据库自动选择Identity、Sequence、Hilo主键生成方式
特点:根据不同的底层数据库采用不同的主键生成方式。由于Hibernate会根据底层数据库采用不同的映射方式,因此便于程序移植,项目中如果用到多个数据库时,可以使用这种方式
b、
<!-- UUID 生成策略 -->
<!-- ID类型 必须是 String -->
<!-- 类似于网卡生成的类型 -->
<class name="Person">
<id name="id">
<generator class="uuid"></generator>
</id>
<property name="name"/>
<property name="weight"/>
</class>
<!--native 生成策略-->
<!-- ID类型 必须是 int-->
<!--由数据库自动递增-->
<id name="id" >
<generator class="native"></generator>
</id>
<id name="id" column="team_id">
<generator class="identity"/>
</id>
2.JPA注解生成方式@GeneratedValue
JPA提供的四种标准用法为TABLE,SEQUENCE,IDENTITY,AUTO.
TABLE:使用一个特定的数据库表格来保存主键。
SEQUENCE:根据底层数据库的序列来生成主键,条件是数据库支持序列。
IDENTITY:主键由数据库自动生成(主要是自动增长型)
AUTO:主键由程序控制。
a、 @GeneratedValue 默认为native
b、 @GeneratedValue(strategy=GenerationType.AUTO)
主键自增长
i. 默认:对 MySQL,使用auto_increment
ii. 对 Oracle使用hibernate_sequence(名称固定)
c、 @GeneratedValue(strategy=GenerationType.IDENTITY)
不能用于oracle,因为oracle不支持IDENTITY; oracle是SEQUENCE
d、 SEQUENCE(@GeneratedValue(strategy=GenerationType.SEQUENCE))
@SequenceGenerator(可自定义在数据库生成指定的sequence名)
例如:
//定义sequence名为teacherSEQ
@SequenceGenerator(name="teacherSEQ",sequenceName="teacherSEQ_DB")
public class Teacher {
private int id;
}
//调用自定义的teacherSEQ
@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="teacherSEQ")
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
e、Table
@Entity
@TableGenerator(name="sequence_team",table="team") //可以设置表名,表列名,表初始值等等信息 从而取代了@Table(name="team")
public class Team {
private int id;
private String name;
@Id
@GeneratedValue(strategy=GenerationType.TABLE,generator="sequence_team")
public int getId() {
return id;
} ........
}
Hibernate的id生成策略有下面几种:[/
color]
1.Increment
用于为long,short或者int类型生成唯一标识,只有在没有其他进程往同一张表中插入数据库时才能使用。在集群下不要使用。
对于集群为什么不要使用,是因为在一个大型的项目中如果我们有很多的服务器为项目提供服务,这样就会出项一种情况,A服务在15:25拿到数据库中的数据的 id为15,此时B服务器向数据库中插入了一条数据,这时数据库中的id为16了,但A服务中的session依旧保存着15,但下一条数据通过A服务向数据库中保存数据的时候session会为id赋值为16,可数据库中的id已经为16了,所以这时保存就会出错。
2.identity:
对 DB2,MySQL,MS SQL Server,Sybase 和 HypersonicSQL 的内置标识字段提供支持。返回的标识符是 long,short 或者 int 类型的。
3.sequence
在 DB2,PostgreSQL,Oracle,SAP DB,McKoi 中使用序列(sequence), 而在 Interbase
中使用生成器(generator)。返回的标识符是 long,short 或者 int 类型的。
4.hilo
使用一个高/低位算法高效的生成 long,short 或者 int 类型的标识符。给定一个表和字段(默认分别是 hibernate_unique_key 和 next_hi)作为高位值的来源。高/低位算法生成的标识符只在一个特定的数据库中是唯一的。
5.seqhilo
使用一个高/低位算法来高效的生成 long,short 或者 int 类型的标识符,给定一个数据库序列(sequence)的名字。
6.uuid
基于一个自定义的算法生成一个128位的UUID。所产生的价值
表示为32个十六进制数字的字符串。
7.guid
在 MS SQL Server 和 MySQL 中使用数据库生成的 GUID 字符串。
8.native
根据底层数据库的能力选择 identity、sequence 或者 hilo 中的一个。
9.assigned
让应用程序在调用 save() 之前为对象分配一个标识符。这是 <generator> 元素没有指定时的默认生成策略。
10.select
通过数据库触发器选择一些唯一主键的行并返回主键值来分配一个主键。
11.foreign
使用另外一个相关联的对象的标识符。它通常和 <one-to-one> 联合起来使用。
12.sequence-identity
一种特别的序列生成策略,它使用数据库序列来生成实际值,但将它和 JDBC3 的getGeneratedKeys 结合在一起,使得在插入语句执行的时候就返回生成的值。目前为止只有面向 JDK 1.4 的 Oracle 10g 驱动支持这一策略。由于 Oracle 驱动程序的一个 bug,这些插入语句的注释被关闭了。
我们通常用的比较多的就是[color=red]native、identity、sequence在一些情况下我们会用到
uuid,其他的就用的很少了。
举例说明uuid
下面来测试一下
uuid,还用原来的Student类,既然是测试uuid那我们的id就必须为
String类型了。
Student类
package cc.tukai.entity;
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;
//@Entity
//@Table(name = "Student")
public class Student implements Serializable {
private static final long serialVersionUID = -5596241291862147220L;
private String id;
private String name;
private int age;
//@Id
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
Student.hbm.xml
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC
"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="cc.tukai.entity">
<class name="Student" table="student">
<id name="id" column="id">
<generator class="uuid"></generator>
</id>
<property name="name" type="java.lang.String">
<column name="name" length="32"></column>
</property>
<property name="age" type="java.lang.Integer">
<column name="age" length="10"></column>
</property>
</class>
</hibernate-mapping>