本章节中将介绍 JPA 中主键生成策略,主键生成策略需要配合 @GeneratedValue 和 @Id 注解一起使用。
在一张表中,主键列的信息通常需要受到程序员的特殊关照。首先,我们需要在主键属性(即使用 @Id 注解修饰的属性)上使用 @GeneratedValue 注解中的 strategy 属性来设值主键的生成方式。
例如:使用 strategy 指定主键生成策略为 GenerationType.TABLE,代码如下:
@GeneratedValue(strategy = GenerationType.TABLE) @Id private Integer id;
其中,strategy 可取值如下:
GenerationType.AUTO
GenerationType.IDENTITY
GenerationType.TABLE
GenerationType.SEQUENCE
把主键生成策略交给 JPA 厂商(Persistence Provider),由它根据具体的数据库选择合适的策略,可以是 Table/Sequence/Identity 中的一种。
假如数据库是 Oracle,则选择 Sequence;如果数据库是 MySQL,则选择 Identity;
注意:如果不做特别指定,JPA 默认是使用这种方式生成主键。
多数数据库支持 IDENTITY,数据库会在新行插入时自动给 ID 赋值,这也叫做 ID 自增长列。例如 MySQL 中可以在创建表时声明 “AUTO_INCREMENT”,例如:
CREATE TABLE `user` ( `id` int(11) NOT NULL AUTO_INCREMENT, `age` int(11) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
注意:该策略在 Oracle 数据库中不支持
有时候为了不依赖于数据库的具体实现,在不同数据库之间更好的移植,可以在数据库中新建序列表来生成主键,序列表一般包含两个字段:
第一个字段引用不同的关系表
第二个字段是该关系表的最大序号
这样,只需要一张序列就可以用于多张表的主键生成。如果不指定表生成器,JPA 厂商会使用默认的表。例如:
Hibernate 会默认使用 hibernate_sequence 表
OpenJPA 会默认使用 openjpa_sequence_table 表
这种方式虽然通用性最好,所有的关系型数据库都支持,但是由于不能充分利用具体数据库的特性,建议不要优先使用。
例如:OpenJPA 的 openjpa_sequence_table 表的 SQL 脚本如下:
CREATE TABLE `openjpa_sequence_table` ( `ID` tinyint(4) NOT NULL, `SEQUENCE_VALUE` bigint(20) DEFAULT NULL, PRIMARY KEY (`ID`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
Oracle 不支持 ID 自增长列而是使用序列的机制生成主键 ID。对此,可以选用序列(Sequence)作为主键生成策略。
如果不指定序列生成器的名称,则使用厂商提供的默认序列生成器,比如 Hibernate 默认提供的序列名称为 hibernate_sequence。
支持的数据库:Oracle、PostgreSQL、DB2