@GeneratedValue 注解用于为 @Id 注解修饰的主键指定值的生成策略,可通过 strategy 属性指定。默认情况下,JPA 自动选择一个最适合底层数据库的主键生成策略:
SQL Server 对应 identity
MySQL 对应 auto increment
Oracle 对于 Sequence
该注解用于指定主键生成策略,默认为 GenerationType.AUTO。
在 javax.persistence.GenerationType 中定义了以下几种可供选择的策略:
GenerationType.IDENTITY
大多数数据库均支持 Identity 主键生成策略,数据库会在新行插入时自动给 ID 赋值,这也叫做 ID 自增长,比如 MySQL 中可以在创建表时声明主键为 AUTO_INCREMENT(自增长)。注意:Oracle 不支持这种方式;
GenerationType.AUTO
把主键生成策略交给JPA厂商(这里是 OpenJPA),由他根据具体的数据库选择合适的策略,可以是 Table/Sequence/Identity 中的任意一种。如果你使用 Oracle 数据库,则选择 Sequence。如果不特别指定策略,默认使用该种方式生成主键;
GenerationType.SEQUENCE
在 MySQL、SQL Server 数据库中支持自增长列,Oracle 却不支持 ID 自增长列而是使用序列的机制生成主键 ID。对此,可以选用序列作为主键生成策略。
如果不指定序列生成器,则使用JPA厂商提供的默认序列生成器,比如 Hibernate 默认提供的序列名称为 hibernate_sequence。
支持的数据库:Oracle、PostgreSQL、DB2
GenerationType.TABLE
有时候为了不依赖于数据库的具体实现,在不同数据库之间更好的移植,可以在数据库中创建一张表来生成主键,这种表被称为“序列表”。序列表一般包含两个字段:
第一个字段作为主键,记录该序列来自那张具体表;
第二个字段保存该关系表最大序号的序列值;
这样,只需要一张表就可以用于多张表的主键生成。
如果不指定表生成器,JPA厂商会使用默认的表,比如 Hibernate 在 Oracle 数据库上默认会使用 hibernate_sequence 表。
这种方式虽然通用性最好,所有的关系型数据库都支持,但是由于不能充分利用数据库生成主键的特性,性能要比使用数据库特有的主键生成策略稍低,建议不要优先使用。
指定在 SequenceGenerator 或 TableGenerator 注释中要使用的主键生成器的名称。默认为空字符串 ""。
数据库主键生成策略数据库支持情况,如下表:
数据库名称 | 支持的id策略 |
mysql | GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY 不支持GenerationType.SEQUENCE |
oracle | strategy=GenerationType.AUTO GenerationType.SEQUENCE GenerationType.TABLE 不支持GenerationType.IDENTITY |
postgreSQL | GenerationType.TABLE GenerationType.AUTO GenerationType.IDENTITY GenerationType.SEQUENCE 都支持 |
kingbase | GenerationType.TABLE GenerationType.SEQUENCE GenerationType.IDENTITY GenerationType.AUTO 都支持 |
使用 @GeneratedValue 指定 @Id 修饰的主键字段 id 的主键生成策略为 GenerationType.IDENTITY),代码如下:
@Entity @Table(name = "users") public class UserEntity { // 执行主键,和主键生成策略 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Integer id; // ... }
注意,@GeneratedValue 注解还可以用在 setter 方法上面。代码如下:
@Entity @Table(name = "users") public class UserEntity { private Integer id; // 执行主键,和主键生成策略 @Id @GeneratedValue(strategy = GenerationType.IDENTITY) public Integer getId() { return id; } // ... }