JPA 的 id 生成策略
JPA 有一个@GeneratedValue
注解,有一个strategy
attribute,如@GeneratedValue(strategy = GenerationType.IDENTITY)
。
常见的可选策略主要有IDENTITY
和SEQUENCE
。
GenerationType.IDENTITY
要求底层有一个 integer 或者 bigint 类型的自增列( auto-incremented column)。自增列的赋值必须在插入操作之后发生,因为这个原因,Hibernate 无法进行各种优化(特别是 JDBC 的 batch 处理,一次 flush 操作会产生很多条insert
语句,分别执行)。如果事务回滚,自增列的值就会被丢弃。数据库在这个自增操作上有个高度优化的轻量级锁机制,性能非常棒。
MySQL 支持这种 id 生成策略,
使用 MySQL 应该尽量使用这个策略,即使它无法优化。
JPA 用它生成 id,会一条一条地插入新的 entity。
GenerationType.SEQUENCE
数据库有一个所谓的 sequence 对象,可以通过 select (而不是 insert )来获取下一个数。
它也可以指定一个特殊的 SequenceGenerator,而不是只使用数据库自带的。
MySQL 不支持这种 id 生成方式,Oracle 支持。
*JPA 用它生成 id,会一条一条地 select 出新的 value,然后再 batch insert 新的 entity
jdbc 生成的隐藏 sql
在使用MySQL时,若表中含自增字段(auto_increment类型),则向表中insert一条记录后,可以调用last_insert_id()(对应的操作就是在事务的 insert 里偷偷插入这样一个语句SELECT LAST_INSERT_ID()
)来获得最近insert的那行记录的自增字段值(一个bigint类型的64-bit值)。
jdbc/mybatis 就是用这样一个语句来获取最新的 id 并绑定在最新的 orm 对象上的。
参考文献: