22.3 主键生成规则
@Id配置主键的同时,也要用 @GeneratedValue配置主键生成规则。主键生成规则也称为主键生成策略,负责维护新实体的主键值。用得最多的策略是自增长策略。 Hibernate还支持其他的多种主键生成规则。这些生成规则有些是数据库提供的,有些是Hibernate提供的。
22.3.1 @主键生成规则
到目前为止,@注解只支持4种主键生成策略:GenerationType.AUTO、GenerationType. TABLE、GenerationType. SEQUENCE、GenerationType. IDENTITY,意义分别为:
● GenerationType.AUTO:自动方式,根据底层数据库自动选择。如果为MySQL等支持自增长类型的数据库,则为自增长类型(auto_increment)。
● GenerationType.TABLE:使用指定的表来决定主键的取值,一般结合@TableGenerator使用,例如:
n
@Id
@TableGenerator(name = "tb_cat_gen", allocationSize = 1)
@GeneratedValue(strategy = GenerationType.TABLE, generator = "tb_cat_gen")
private Integer id;
n
● GenerationType. SEQUENCE:使用Sequence来决定主键的取值,适合Oracle、DB2、PostgreSQL、SAP DB等支持Sequence的数据库,一般结合@ SequenceGenerator使用。注意某些数据库如Oracle等没有自增长类型,只能使用Sequence,例如:
n
@Id
@SequenceGenerator(name = "seq_cat", allocationSize = 25)
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_cat")
@Column(name = "id")
private Integer id;
n
● GenerationType. IDENTITY:支持DB2、MySQL、MS SQL Server、Sybase与 HypersonicSQL数据库的identit类型主键。
22.3.2 XML主键生成规则
XML配置中支持的主键生成规则要多得多,例如:
● native:取决于数据库,相当于GenerationType.AUTO。
● identity:使用identity类型,相当于GenerationType. IDENTITY。
● sequence:使用sequence,相当于GenerationType. SEQUENCE。需要指定sequence的名称,例如:
n
<id name="id" type="long" column="person_id">
<generator class="sequence"> <!-- 使用sequence主键 -->
<param name="sequence">person_id_sequence</param>
</generator>
</id>
n
● increment:自增长类型,由Hibernate而不是数据库维护,因此即使Oracle等不支持自增长类型的数据库也可以使用。
● hilo:hi/low算法,使用指定的表给主键赋值,相当于GenerationType.TABLE。需要指定表名、列名等,例如:
n
<id name="id" type="long" column="cat_id">
<generator class="hilo">
<param name="table">hi_value</param>
<param name="column">next_value</param>
<param name="max_lo">100</param>
</generator>
</id>
n
● seqhilo:基于sequence的hilo算法,例如:
n
<id name="id" type="long" column="cat_id">
<generator class="seqhilo">
<param name="sequence">hi_value</param>
<param name="max_lo">100</param>
</generator>
</id>
n
● uuid:使用128位的UUID算法计算一个唯一的值,会使用IP地址及相关的计算机硬件信息。计算结果为32位的16进制数,对应的主键类型必须为String。
● guid:使用MySQL或者MS SQL Server等数据库提供的GUID值。
● assigned:默认值,不使用任何策略,在保存进数据库之前必须使用setter方法赋值。
● select:使用数据库触发器赋值。
● foreign:使用外键赋值,在一对一实体关系时,可保证关系双方的Id保持一致。
MySQL数据库与Hibernate都提供自增长策略,但是原理是不一样的。如果采用MySQL的自增长,插入数据时Hibernate生成的SQL语句中将不包含id 主键列数据。该主键的当前值、下一个值由数据库自己维护。如果使用Hibernate的自增长,插入数据时Hibernate生成的SQL语句将包含id 主键列,并由Hibernate维护该主键的当前值以及下一个值。
% 注意:对于普通的应用来说,数据库自增长与Hibernate自增长在使用上没有区别。但是如果某数据库同时被两个Hibernate程序使用,那么此时使用Hibernate自增长将会出现错误。例如,如果当前主键值为10,那么Hibernate会认为下个主键值为11,两个Hibernate程序插入数据时都会将主键值设为11,这时会因为主键冲突而导致其中一个写数据失败。