GeneratedValue策略之间的区别

71
Doctrine 文档 中提到了 @GeneratedValue 注解有几种不同的策略:

  • AUTO
  • SEQUENCE
  • TABLE
  • IDENTITY
  • UUID
  • CUSTOM
  • NONE

请问有人能够解释一下这些策略之间的差异吗?

3个回答

111

查看最新的Doctrine文档

以下是概要: 可能的生成策略列表:

AUTO(默认):告诉Doctrine选择所使用数据库平台首选的策略。首选策略为MySQL、SQLite和MsSQL的IDENTITY,以及Oracle和PostgreSQL的SEQUENCE。此策略提供全面的可移植性。

SEQUENCE:告诉Doctrine使用数据库序列进行ID生成。该策略目前不能完全可移植。序列受Oracle、PostgreSQL和SQL Anywhere支持。

IDENTITY:告诉Doctrine在数据库中使用特殊的自增列,在插入行时生成值。此策略目前不能完全可移植,并且由以下平台支持:

  • MySQL/SQLite/SQL Anywhere => AUTO_INCREMENT
  • MSSQL => IDENTITY
  • PostgreSQL => SERIAL

TABLE:告诉Doctrine使用单独的表进行ID生成。此策略提供全面的可移植性。此策略尚未实现!

NONE:告诉Doctrine标识符由您的代码分配和生成。分配必须在将新实体传递给EntityManager#persist之前进行。 NONE与完全省略@GeneratedValue相同。

自版本2.3起:

UUID:告诉Doctrine使用内置的通用唯一标识符生成器。此策略提供全面的可移植性。


2
你引用了2.0文档,所以我猜表格现在可用了。如果你有任何想法,请告诉我UUID的情况。 - superhero
我从不使用Doctrine 2中的这种生成器ID。我只能说,如果您的数据库支持UUID生成,则可以使用此功能。这仅适用于分布式系统。对于Oracle数据库,它将通过SYS_GUID()oracle命令生成ID。这是由Doctrine DBAL层完成的。而且你是正确的,表生成器现在在当前版本的Doctrine中可用。 - BADAOUI Mohamed
3
关于如何使用 CUSTOM 策略的信息,我刚刚在这里发布了一个示例:[https://dev59.com/Dmox5IYBdhLWcg3wnVmz#28561017]。 - enricog
我的Hibernate配置看起来像这样 <generator class="increment" />。它属于哪种策略? - Chiến Nghê

6

当然,被接受的答案是正确的,但它需要进行以下更新

根据文档注释部分:

此注释是可选的,仅在与@Id一起使用时才有意义。如果没有使用@Id指定此注释,则默认使用NONE策略。

strategy属性是可选的

根据文档基本映射部分:

SEQUENCE:告诉Doctrine使用数据库序列进行ID生成。该策略目前不能提供完全的可移植性。序列由OraclePostgreSqlSQL Anywhere支持。

IDENTITY:告诉Doctrine在数据库中使用特殊的身份列,在插入行时生成一个值。该策略目前不能提供完全的可移植性,以下平台支持此策略:

  • MySQL/SQLite/SQL Anywhere(AUTO_INCREMENT)
  • MSSQL(IDENTITY)
  • PostgreSQL(SERIAL)。

Downvote

关于某人给出的负评,应注意到SQL Anywhere已被添加,接受的答案需要进行微小的更新


4
从程序员的角度来看,它们都实现了相同的结果:为主键字段提供唯一值。严格来说,还有两个进一步满足的条件,即:键也必须是强制性的且不能为空(not null)。 唯一的区别在于提供主键值的内部实现。此外,还需要考虑性能和数据库兼容性等因素。不同的数据库支持不同的策略。
最容易理解的是序列(SEQUENCE),这通常也是产生最佳性能优势的方法。在这里,数据库维护一个内部序列,其nextval通过另一个SQL调用访问,如下所示:
SELECT nextval ('hibernate_sequence')

下一个值在插入每一行数据时进行分配。虽然需要额外的 SQL 调用,但对性能影响很小。使用 SEQUENCE,可以使用 @SequenceGenerator 注释指定初始值(默认为 1)和分配大小(默认为 50):
@SequenceGenerator(name="seq", initialValue=1, allocationSize=100)

"IDENTITY"策略依赖于数据库通过在表中维护一个额外的列来生成主键,每当插入新行时自动生成下一个值。对于每个类型层次结构都需要单独的标识生成器。
"TABLE"策略依赖于一个单独的表来存储和更新序列,并在每次插入新行时使用悲观锁来维护序列,因此是所有选项中最慢的策略。值得注意的是,可以使用"@TableGenerator"注释来指定生成器名称、表名称和模式来实现此策略。"
@TableGenerator(name="book_generator", table="id_generator", schema="bookstore")

使用UUID选项,持久性提供程序(例如Hibernate)生成形式为:'8dd5f315-9788-4d00-87bb-10eed9eff566'的通用唯一标识符。要选择此选项,只需在数据类型为UUID的字段声明上方应用@GeneratedValue注释即可,例如:

@Entity
public class UUIDDemo {

    @Id
    @GeneratedValue
    private UUID uuid;

    // ...
}

最后,AUTO策略是默认选项,使用此选项时,持久化提供程序会为所使用的数据库选择最优策略。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接