java - jpa 序列 ID 生成

标签 java hibernate jpa orm hibernate-mapping

在实体持久化到数据库之前但立即在构造函数中为实体分配 ID 可以获得巨大的值(value):您的 equals/hashcode 实现变得微不足道,and it saves many headaches .

当实体相等性基于 == 时,我看到了问题:代理进入 session ,当它作为真实对象解包时,你得到 equals() 返回 false

并且当您覆盖equalshashcode 以使用生成的ID 时,因为该ID 仅在persist() 上生成,所有非- 持久实体的 ID null 因此彼此相等。

据我了解,当您使用传统的 ID 生成技术(比方说自动增量)时,ID 是在刷新实体管理器时生成的。当您使用基于序列的解决方案时,它会在持续时间内生成。

那篇文章和我目前的理解说最简单的解决方案是在创建时分配一个 ID,而不是持久化或刷新时间。并且序列看起来可达,但 JPA 决定反对它。由于使用序列获取 ID 很便宜(因为您可以预取),为什么 JPA 没有提供至少一个选项来在对象构造时已经获取基于序列的 ID?如果实体最终没有真正持久化,则存在浪费一些 ID 的风险,但我认为这不是一个大问题。

除此之外,就解决方案的简单性和可理解性而言,唯一“不妥协”的似乎是 UUID,它有自己的问题。

我错过了什么吗?是否有一些 JPA 身份生成器或一些基于序列并允许在构建时提供 ID 的库?

最佳答案

使用 assigned identifier从写作的角度来看是最好的方法。它在所有 entity state transitions 中也是一致的您甚至可以在 JDBC 级别批处理多个插入。

在读取和索引方面,数字列表现更好,分配的标识符是唯一逻辑键(社会保险号)或唯一标识符(例如 UUID)。使用应用程序级唯一分配标识符很复杂,因为您可能有多个应用程序节点(在集群中),或者您希望同步来自应用程序内部和外部源(数据库客户端实用程序)的插入。

对于数据库分配的标识符,您需要考虑您的选择如何影响刷新。 Hibernate 尝试推迟 Persistence Context flushing up until the last possible moment .这种策略传统上被称为事务性后写。

write-behind 与 Hibernate 刷新更相关,而不是任何逻辑或物理事务。在一次交易中,flush可能会发生多次。

刷新的更改仅对当前数据库事务可见。在提交当前事务之前,其他并发事务看不到任何更改。

IDENTITY requires flushing ,而序列是非事务性的,因此它不需要刷新。 IDENTITY 禁用 JDBC 插入批处理,并且不支持预分配。

JPA 无法在实体构造时分配标识符,因为新实例只能通过调用 EntityManager.persist() 来持久化。 JPA 需要明确的“实体状态转换”。

浪费序列标识符不是什么大问题。即使序列值存在间隙,数据库也能正常运行。使用 bigint 列可以保证您实际上不会用完序列标识符。与具有较高死锁争用风险的事务性分配相比,具有偶尔出现间隙的非事务性序列标识符分配更好。

关于java - jpa 序列 ID 生成,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27062797/

相关文章:

java - 让火箭彼此相邻显示

java - 为什么 setIcon 不在 JButton 上显示图像?

hibernate - 如何避免 HQL 和 Criteria 中不必要的选择和联接

java - JPA @Id and insertable = false, updatable = false 抛出异常

java无重复随机生成器

java - 如何为单个方法设置show_sql Hibernate参数?

java - jboss5 类加载器问题,spring 和 hibernate 尝试解析 applicationContext.xml

java - 如何在where子句中使用枚举作为jpa中的常量检查

json - 在一个查询中更新多行,但我们期望的输入来自多个数据的 json 对象

java - Bash 脚本——使用expect 从标准输出读取