理解JPA序列生成器

3

我正在使用Spring Data JPA的序列生成器为实体分配主键。

模型包含:

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

对应的序列定义(针对 SQL Server 数据库):
CREATE SEQUENCE dbo.seq_post START WITH 1 INCREMENT BY 5;

由于我想从100开始而不是1,因此我更新了SQL脚本如下:

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

然后我遇到了如此所述的问题。我通过那里提到的解决方案来解决它。

这让我想知道,当我想让数据库序列从1开始时,为什么不会发生这个问题?根据这里提到的答案,我预期id不会从1开始,但实际上并非如此。这是为什么呢?


因为Hibernate足够智能,不会给出负的序列号。从这个角度来看,如果你从1开始,那么这是一个边缘情况。 - Tamás Pollák
不,情况并非如此。我遇到过一种情况,其中负ID被分配为PK。 - JavaLearner
1
“start with 1”似乎是一个独特的例外,对于所有其他值,“allocationSize”都会减去,所以如果您将序列设置为例如“start with 3”,则您将获得第一个“ID”为负数(3-allocationSize)。 - Marmite Bomber
实际上,Hibernate开源的,因此您应该能够找到new_generator_mappings的源代码。您会发现一行代码,其中包含if (nextval == 1) ... else ... subtract allocationSize - Marmite Bomber
1个回答

2
首先,请检查是否将属性hibernate.id.new_generator_mappings设置为true,如建议所述。
然后,您可以通过调整序列INCREMENT BYallocationSize来进行正确调整。
如果您想要以特定值开始ID,则似乎遵守以下规则:
  • 要从1开始,请将序列设置为START WITH 1(这似乎是一个例外)

  • 要从X > 1开始,请将序列设置为START WITH X + 50(对于X < 1同样适用)

例如,要从5000开始,默认的allocationSize50,请定义序列如下。
create sequence sub_seq
       START WITH 5050
       INCREMENT BY 50
       NOCACHE;

请注意,我正在使用NOCACHE选项,因为我假设Hibernate是此序列的唯一用户,所以缓存并没有真正意义(实际上被分配大小替换)。
你还会在会话之间丢失约1/2的IDallocationSize,而且你不想增加额外的缓存ID的丢失。

你能否在你的回答中添加这个链接 https://docs.jboss.org/hibernate/orm/5.2/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators,以便未来的读者知道它? - JavaLearner
我的应用程序已经运行,并且我手动将DB序列重置为1,因此我的下一个ID从1-allocationSize开始,这就是混淆的原因。另外,我无法找到执行此逻辑if (nextval == 1) ... else ... subtract allocationSize的源代码。如果您能分享它,那就太好了。 - JavaLearner
谢谢您提供详细的答案。我之前不知道NOCACHE选项。其他读者可能也会对https://dev59.com/x6Pia4cB1Zd3GeqPvkHA#44988410感兴趣。 - JavaLearner

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接