@GeneratedValue
是属性或方法级别的注解,它结合 @Id
注解为主键的值提供生成策略的规范。
参数 |
类型 |
描述 |
strategy |
GenerationType |
主键生成策略。可选值: GenerationType.TABLE GenerationType.SEQUENCE GenerationType.IDENTITY GenerationType.AUTO 默认是 GenerationType.AUTO。 |
generator |
String |
主键生成器的名称。该名称为 @TableGenerator 或 @SequenceGenerator 注解中 name 参数的值。默认为持久化提供者(如 Hibernate)提供的id生成器。 |
1. @GeneratedValue
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue private Long id; private String name; private String mail; }
|
产生的 DDL 语句(MySQL):
1 2 3 4 5 6
| CREATE TABLE `person` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `mail` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
1.1 GenerationType.TABLE
该策略使用一个特殊的数据库表来为各个实体分配主键,并确保主键值的唯一性。它不依赖环境和数据库系统的具体实现,在不同数据库之间可以很容易的进行移植。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.TABLE) private Long id; private String name; private String mail; }
|
在 Hibernate + MySQL 环境产生的 DDL 语句:
1 2 3 4 5 6 7 8 9 10 11 12
| CREATE TABLE `person` ( `id` bigint(20) NOT NULL, `mail` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `hibernate_sequences` ( `sequence_name` varchar(255) NOT NULL, `sequence_next_hi_value` bigint(20) DEFAULT NULL, PRIMARY KEY (`sequence_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
其中,hibernate_sequences 表就是用来为各个实体分配主键的,sequence_name 用于存储各个实体名称,sequence_next_hi_value 则是用于存储各个实体的下一个主键的值。
每次保存 Person 实体对象的数据的时候,首先会到 hibernate_sequences 表中查询该实体名称是否已经存在,若不存在,则向 hibernate_sequences 表插入一行该实体名称的记录,若已经存在,则直接取出 sequence_next_hi_value 的值作为本次 Person 数据的主键值,接着更新 hibernate_sequences 表的记录,使该实体名称的记录的 sequence_next_hi_value 值加1。最后保存 Person 实体对象的记录。
1.1.1 @TableGenerator
表生成器,GenerationType.TABLE 策略通常结合该注解一起使用。
参数 |
类型 |
描述 |
name |
String |
生成器的名称,它可以被一个或多个类引用为主键的生成器。 |
table |
String |
生成器表的名称。默认为持久化提供者(如 Hibernate)提供的名称。 |
catalog |
String |
生成器表的 catalog,默认为数据库系统缺省的 catalog。 |
schema |
String |
生成器表的 schema,默认为用户缺省的 schema。 |
pkColumnName |
String |
生成器表的主键列的名称,默认为持久化提供者(如 Hibernate)提供的名称。 |
valueColumnName |
String |
生成器表存储生成的值的列的名称,默认为持久化提供者(如 Hibernate)提供的名称。 |
pkColumnValue |
String |
生成器表中的主键值,用于将不同的实体区分开来。默认为实体名称(@Entity 注解的 name 参数的值)。 |
initialValue |
int |
用于初始化生成器生成的初始值。默认值是0。在 Hibernate 环境中,需要开启 hibernate.id.new_generator_mappings=true (Spring JPA 配置为:spring.jpa.hibernate.use-new-id-generator-mappings=true ),否则此参数无效。并且如果实体记录已经存在生成器表中,此参数也无效(即只有当实体记录第一次写入生成器表中时此参数生效)。 |
allocationSize |
int |
每次分配的值的数量大小,用完之后再分配此数量的值,默认为50。 |
uniqueConstraints |
UniqueConstraint[] |
表的唯一约束,参考 @UniqueConstraint |
indexes |
Index[] |
表的索引,参考 @Index |
注:catalog 和 schema 可参考 catalog 和 schema 的区别。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "pkGenerator") @TableGenerator( name = "pkGenerator", table = "pk_sequences", pkColumnName = "entity_name", valueColumnName = "sequence_value", allocationSize = 10 ) private Long id; private String name; private String mail; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Entity(name = "user") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.TABLE, generator = "pkGenerator") @TableGenerator( name = "pkGenerator", table = "pk_sequences", pkColumnName = "entity_name", valueColumnName = "sequence_value", allocationSize = 10 ) private Long id; private String name; }
|
产生的 DDL 语句(MySQL):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| CREATE TABLE `person` ( `id` bigint(20) NOT NULL, `mail` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `user` ( `id` bigint(20) NOT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8; CREATE TABLE `pk_sequences` ( `entity_name` varchar(255) NOT NULL, `sequence_value` bigint(20) DEFAULT NULL, PRIMARY KEY (`entity_name`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
1.2 GenerationType.SEQUENCE
某些数据库系统(如:Oracle、DB2、PostgreSQL 等)底层支持使用序列对象来为表的主键提供唯一值,而对于不支持序列对象的数据库(如:MySQL、SQLServer),则不应使用此策略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; private String name; private String mail; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| @Entity(name = "user") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE) private Long id; private String name; public Long getId() { return id; } public void setId(Long id) { this.id = id; } public String getName() { return name; } public void setName(String name) { this.name = name; } }
|
这种方式是多个实体共用同一个序列对象,这将导致各个实体分配到的序列值不连续,并且消耗加快。
1.2.1 @SequenceGenerator
序列生成器,GenerationType.SEQUENCE 策略通常结合该注解一起使用。
参数 |
类型 |
描述 |
name |
String |
生成器的名称,它可以被一个或多个类引用为主键的生成器。 |
sequenceName |
String |
序列对象的名称,默认为持久化提供者(如 Hibernate)提供的名称。 |
catalog |
String |
序列生成器的 catalog。 |
schema |
String |
序列生成器的 schema。 |
initialValue |
int |
用于初始化序列对象生成的初始值。默认值是1。 |
allocationSize |
int |
每次分配的值的数量大小,用完之后再分配此数量的值,默认为50。 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "personSeqGenerator") @SequenceGenerator( name = "personSeqGenerator", sequenceName = "PERSON_SEQ", allocationSize = 10 ) private Long id; private String name; private String mail; }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
| @Entity(name = "user") public class User implements Serializable { @Id @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "userSeqGenerator") @SequenceGenerator( name = "userSeqGenerator", sequenceName = "USER_SEQ", allocationSize = 10 ) private Long id; private String name; }
|
1.3 GenerationType.IDENTITY
大部分数据库系统(如:MySQL、SQLServer、DB2、Sybase、HypersonicSQL 等)底层支持表的主键自增长,而对于不支持主键自增长的数据库(如:Oracle),则不能使用此策略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) private Long id; private String name; private String mail; }
|
产生的 DDL 语句(MySQL):
1 2 3 4 5 6
| CREATE TABLE `person` ( `id` bigint(20) NOT NULL AUTO_INCREMENT, `mail` varchar(255) DEFAULT NULL, `name` varchar(255) DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8;
|
1.4 GenerationType.AUTO
自动为特定的数据库选择适当的策略,这是比较常用的策略。
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue(strategy = GenerationType.AUTO) private Long id; private String name; private String mail; }
|
由于 @GeneratedValue
注解默认采用的策略就是 GenerationType.AUTO
,因此可以简写成:
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| @Entity(name = "person") public class Person implements Serializable { @Id @GeneratedValue private Long id; private String name; private String mail; }
|