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

时间:2012-04-06 09:58:52

标签: java hibernate jpa uniqueidentifier id-generation

我正在浏览Hibernate参考指南的Id生成部分和“使用Hibernate的java持久性”

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

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

我也在寻找引爆点。

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

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

有没有可用的文献?

4 个答案:

答案 0 :(得分:89)

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个十六进制数字的字符串。

     

<强> GUID

     

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

     

<强>天然

     

根据底层数据库的功能选择identity,sequence或hilo。

     

<强>分配

     

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

     

选择

     

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

     

<强>外国

     

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

     

<强>序列同一性

     

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

如果要构建一个没有多少并发用户的简单应用程序,可以使用 increment,identity,hilo 等。这些配置很简单,并且在db中不需要太多编码。

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

更新: 最近我们遇到了一个idendity问题,其中基本类型(int)通过使用warapper类型(整数)来修复。

答案 1 :(得分:43)

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

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

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

对于数字标识符you have three options

  • IDENTITY
  • SEQUENCE

当您无法使用SEQUENCE(例如MySQL)时,IDENTITY是一个不错的选择,因为it disables JDBC batch updates

SEQUENCE是首选选项,尤其是与pooled or pooled-lo等标识符优化器一起使用时。

TABLE is to be avoided at any cost因为它使用一个单独的事务来获取标识符和行级锁定,这些锁定的扩展性很差。

答案 2 :(得分:20)


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

选择正确的发电机是一项复杂的任务,但重要的是尽快尝试正确 - 迟到的迁移可能是一场噩梦。

有点偏离主题,但很有可能提出一个点通常被忽视,这是在应用程序之间共享密钥(通过API)。我个人总是喜欢代理键,如果我需要与其他系统通信我的对象,我不会暴露我的密钥(即使它是代理密钥) - 我使用额外的“外部密钥”。作为一名顾问,我不止一次看过使用对象密钥的“伟大”系统集成(“它就是让它只是使用它”的方法)只是为了找到一两年后,一方有关键范围或某事的问题需要在系统上进行深度迁移以暴露其内部密钥的类型。公开你的密钥意味着将代码的一个基本方面暴露给外部约束不应该真正暴露给它。

答案 3 :(得分:2)

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