【问题标题】:Understanding JPA sequence generator了解 JPA 序列生成器
【发布时间】:2021-08-11 10:05:48
【问题描述】:

我正在使用 spring data JPA 的序列生成器将主键分配给实体。

模型包含:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "seq_post")
@SequenceGenerator(name = "seq_post", allocationSize = 5)
private Long id;

对应的序列定义(SQL Server DB):

CREATE SEQUENCE dbo.seq_post START WITH 1 INCREMENT BY 5;

由于我想从 100 而不是 1 开始 id,所以我将 sql 脚本更新为

CREATE SEQUENCE dbo.seq_post START WITH 100 INCREMENT BY 5;

然后我遇到了here 提到的问题。我通过那里提到的解决方案修复了它。

这让我想知道,当我希望 DB 序列从 1 开始时,为什么不会发生此问题?根据here 提到的答案,我希望 id 不会从 1 开始,但这不会发生。为什么会这样?

【问题讨论】:

  • 因为 Hibernate 足够聪明,不会给出负序号。从这个角度来看,这是一个边缘情况,当你从 1 开始时。
  • 不,事实并非如此。我遇到了将负 id 分配为 PK 的情况。
  • 好吧,start with 1 似乎是一个独特的例外,对于所有其他值,allocationSize减去,所以你是对的,如果你将序列设置为例如start with 3,你会得到第一个ID否定(3-allocationSize)
  • 其实Hibernate开源的,所以应该可以找到new_generator_mappings的源码。你会在那里找到if (nextval == 1) ... else ... subtract allocationSize

标签: java spring-boot hibernate spring-data-jpa


【解决方案1】:

首先检查您是否将属性hibernate.id.new_generator_mappings 设置为truerecomended

比你正确调整allocationSize 与序列INCREMENT BY

如果您想开始 ID 具有特定值,它似乎遵循以下规则:

  • 一个开头,将序列设置为START WITH 1(这似乎是一个例外)

  • X > 1开始设置序列START WITH X + 50(其实X < 1也是如此)

例如以5000 开头,使用50 的默认allocationSize 定义序列如下

create sequence sub_seq
       START WITH 5050
       INCREMENT BY 50
       NOCACHE;

请注意,我使用的是 NOCACHE 选项,因为我假设 Hibernate 是此序列的唯一用户,因此 缓存 并不是真正的充分(实际上替换为分配大小。

你也松散在会话之间大约。 IDs 的 allocationSize 的 1/2,并且您不希望增加缓存的 IDs 的额外损失。

【讨论】:

  • 您能否也将此docs.jboss.org/hibernate/orm/5.2/userguide/html_single/… 添加到您的答案中,以便将来的读者知道它?
  • 我启动并运行了我的应用程序,我手动将 DB 序列重置为 1,并且我的下一个 id 从 1-allocationSize 开始,因此造成了混乱。我也找不到执行此逻辑if (nextval == 1) ... else ... subtract allocationSize 的源代码。如果能分享出来就好了。
  • 感谢您的详细解答。我不知道NOCACHE 选项。其他读者可能也对stackoverflow.com/a/44988410感兴趣
猜你喜欢
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 2021-04-07
  • 1970-01-01
  • 2018-04-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多