使用JPA和Hibernate时如何选择ID生成策略


102

我正在阅读《 Hibernate参考指南》的ID生成部分和“ Hibernate的Java持久性”

Hibernate和JPA结合在一起有很多选项。

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

我也在寻找引爆点。

例如,hilo策略有望减少竞争。我假设必须对此进行权衡取舍。

我想受权衡教育。

有没有可用的文献?

Answers:


92

API文档都对这个很清楚。

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

增量

生成长,短或整数类型的标识符,仅当没有其他进程将数据插入同一表时才唯一。不要在集群中使用。

身份

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

序列

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

你好

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

seqhilo

在给定命名数据库序列的情况下,使用hi / lo算法高效地生成long,short或int类型的标识符。

uid

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

吉德

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

本机

根据基础数据库的功能选择身份,序列或hilo。

已分配

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

选择

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

国外

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

序列同一性

一种特殊的序列生成策略,该策略利用数据库序列进行实际值生成,但将其与JDBC3 getGeneratedKeys结合使用以返回生成的标识符值,作为插入语句执行的一部分。仅针对JDK 1.4的Oracle 10g驱动程序支持此策略。由于Oracle驱动程序中的错误,因此禁用了对这些插入语句的注释。

如果要构建一个并发用户不多的简单应用程序,则可以进行增量,标识,hilo等操作。这些配置简单,并且不需要在数据库内部进行大量编码。

您应该根据数据库选择序列引导。这些安全且更好,因为id生成将在数据库内部进行。

更新: 最近我们遇到了一个有关身份认同的问题,其中原始类型(int)通过使用warapper类型(Integer)得以解决。


非常感谢您的回复。我已经看过文档了。但是,我正在寻找人们为什么会使用hilo和seqhilo之类的东西。我们什么时候做出选择。有哪些用例可供选择。

当存在序列或引导等简单明了的内容时,开发人员可能需要选择其他途径。

1
我已经更新了答案。实际上,增量,标识,hilo等比较简单。但它们不适合企业应用程序。保留所有选项不是问题,但是请确保使用最合适的选项!
ManuPK

是的 到目前为止,我还没有投票或接受的特权。

如果您有时间,请注意让我知道更多细节。

45

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

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

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

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

  • 身份
  • 序列

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

SEQUENCE是首选选项,尤其是在与标识符优化器(例如pooled或pooled-lo)一起使用时

应该不惜一切代价避免使用TABLE,因为它使用单独的事务来获取标识符和行级锁,而伸缩性很差。


20


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

选择正确的生成器是一项复杂的任务,但是尽早使它变得正确很重要-延迟迁移可能是一场噩梦。

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


By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.