【问题标题】:How to choose the id generation strategy when using JPA and Hibernate使用 JPA 和 Hibernate 时如何选择 id 生成策略
【发布时间】:2012-04-19 23:31:32
【问题描述】:

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

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

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

我也在寻找引爆点。

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

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

有文献吗?

【问题讨论】:

    标签: java hibernate jpa uniqueidentifier id-generation


    【解决方案1】:

    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 字符串。

    原生

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

    已分配

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

    选择

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

    外国

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

    序列身份

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

    如果您正在构建一个并发用户不多的简单应用程序,您可以选择 increment、identity、hilo 等。这些配置简单,不需要在 db 内进行太多编码。

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

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

    【讨论】:

    • 非常感谢您的回复。我已经看过文档了。但是,我正在寻找为什么人们会使用 hilo 和 seqhilo 之类的东西。我们什么时候做出这样的选择。选择的用例是什么。
    • 当有像 sequence 或 guid 这样简单的东西时,需要开发人员选择其他途径。
    • 我已经更新了我的答案。实际上 increment、identity、hilo 等更简单。但它们不适合企业应用程序。保留所有选项不是问题,但请确保使用最适合您的选项!
    • 是的。到目前为止,我没有资格投票或接受。
    • 我正在研究更多细节,如果你有时间请告诉我。
    【解决方案2】:

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

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

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

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

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

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

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

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

    【讨论】:

      【解决方案3】:


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

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

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

      【讨论】:

        【解决方案4】:

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

        【讨论】:

        • 那个视频看起来很眼熟。
        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-09
        • 1970-01-01
        • 1970-01-01
        • 2012-06-06
        • 1970-01-01
        • 2022-01-16
        相关资源
        最近更新 更多