107

我正在阅读 Hibernate 参考指南的 Id generation 部分和“java persistence with Hibernate”

结合 Hibernate 和 JPA 有很多可用的选项。

我正在寻找有关如何选择特定 id 生成策略的进一步文档。

我也在寻找引爆点。

例如,hilo 策略有望减少争用。我假设必须有与此选择相关的权衡。

我想接受有关权衡的教育。

有没有可用的文献?

4

4 回答 4

96

API Doc对此非常清楚。

所有生成器都实现接口 org.hibernate.id.IdentifierGenerator。这是一个非常简单的界面。一些应用程序可以选择提供自己的专用实现,然而,Hibernate 提供了一系列内置的实现。内置生成器的快捷方式名称如下:

增量

生成 long、short 或 int 类型的标识符,这些标识符仅在没有其他进程将数据插入同一个表时才是唯一的。不要在集群中使用。

身份

支持 DB2、MySQL、MS SQL Server、Sybase 和 HypersonicSQL 中的标识列。返回的标识符是 long、short 或 int 类型。

序列

使用 DB2、PostgreSQL、Oracle、SAP DB、McKoi 中的序列或 Interbase 中的生成器。返回的标识符是 long、short 或 int 类型

希洛

使用 hi/lo 算法有效地生成 long、short 或 int 类型的标识符,给定表和列(默认情况下分别为 hibernate_unique_key 和 next_hi)作为 hi 值的来源。hi/lo 算法生成仅对特定数据库唯一的标识符。

seqhilo

给定一个命名的数据库序列,使用 hi/lo 算法有效地生成 long、short 或 int 类型的标识符。

uuid

使用 128 位 UUID 算法生成在网络中唯一的字符串类型标识符(使用 IP 地址)。UUID 被编码为长度为 32 位十六进制数字的字符串。

向导

在 MS SQL Server 和 MySQL 上使用数据库生成的 GUID 字符串。

本国的

根据底层数据库的功能选择身份、序列或 hilo。

分配

让应用程序在调用 save() 之前为对象分配一个标识符。如果未指定任何元素,这是默认策略。

选择

通过按某个唯一键选择行并检索主键值来检索由数据库触发器分配的主键。

外国的

使用另一个关联对象的标识符。它通常与主键关联一起使用。

序列同一性

一种专门的序列生成策略,它利用数据库序列来生成实际值,但将其与 JDBC3 getGeneratedKeys 结合以返回生成的标识符值作为插入语句执行的一部分。此策略仅在面向 JDK 1.4 的 Oracle 10g 驱动程序上受支持。由于 Oracle 驱动程序中的错误,对这些插入语句的注释被禁用。

如果您正在构建一个并发用户不多的简单应用程序,您可以使用增量、身份、hilo等。这些配置简单,不需要在 db 中进行太多编码。

您应该根据您的数据库选择序列guid 。这些是安全且更好的,因为id生成将发生在数据库内部。

更新: 最近我们遇到了一个身份问题,原始类型 (int) 已通过使用 warapper 类型 (Integer) 来解决。

于 2012-04-06T12:59:18.600 回答
56

基本上,您有两个主要选择:

  • 您可以自己生成标识符,在这种情况下,您可以使用分配的标识符。
  • 你可以使用@GeneratedValue注解,Hibernate 会为你分配标识符。

对于生成的标识符,您有两个选项:

  • UUID 标识符。
  • 数字标识符。

对于数字标识符,您有三个选项:

IDENTITY仅当您无法使用SEQUENCE(例如 MySQL)时才是一个不错的选择,因为它会禁用 JDBC 批量更新。

SEQUENCEpooled是首选选项,尤其是与类似or的标识符优化器一起使用时pooled-lo

TABLE应避免使用,因为它使用单独的事务来获取可伸缩性较差的标识符和行级锁。

于 2016-07-15T08:11:41.080 回答
20


前段时间我写了一篇关于 Hibernate 密钥生成器的详细文章: http ://blog.eyallupu.com/2011/01/hibernatejpa-identity-generators.html

选择正确的生成器是一项复杂的任务,但重要的是要尽快尝试并使其正确——延迟迁移可能是一场噩梦。

有点离题,但很好的机会提出一个通常被忽视的观点,即在应用程序之间共享密钥(通过 API)。就我个人而言,我总是更喜欢代理键,如果我需要与其他系统通信我的对象,我不会公开我的密钥(即使它是代理键)——我使用额外的“外部密钥”。作为一名顾问,我不止一次看到使用对象键的“出色”系统集成(“它就在那里,让我们使用它”方法)只是在一两年后发现一方存在键范围或其他问题需要在系统上进行深度迁移以暴露其内部密钥的那种。公开你的密钥意味着你的代码的一个基本方面不应该暴露给外部约束。

于 2012-11-03T09:09:54.953 回答
3

我觉得这个讲座非常有价值https://vimeo.com/190275665,在第 3 点中总结了这些生成器,并在您使用每个生成器时给出了一些性能分析和指南。

于 2017-02-06T21:14:51.110 回答