休眠使用PostgreSQL序列不会影响序列表

我已经将Hibernate配置为使用PostgreSQL序列(通过注释)为主键id列生成值,如下所示:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
@Column(name="id", unique=true, nullable=false)
public int getId() {
    return this.id;
}

我在此配置中看到的是,休眠已经在持久性上分配了>3000的id值,而对已用序列的查询显示以下内容:

database=# select last_value from entity_id_seq;
last_value 
------------
     69

(1 行)

问题:
有什么问题吗?
休眠是否应该与序列表同步?
如果不是,它在哪里存储最后生成的ID?

谢谢。


答案 1

我遇到了同样的问题。它与Hibernate的id分配策略有关。如果您选择GenerationType.SEQUENCE,Hibernate使用HiLo策略,默认情况下,该策略以50个块为单位分配ID。因此,您可以显式设置分配大小值,如下所示:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq", allocationSize=1)
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
@Column(name="id", unique=true, nullable=false)
public int getId() {
    return this.id;
}

不过,我也听说过将HiLo策略与 allocationSize=1 结合使用并不是一个好习惯。有些人建议在必须处理数据库管理的序列时使用GenerationType.AUTO代替

更新:我最终确实选择了 allocationSize=1,现在事情似乎像预期的那样工作。我的应用程序是这样的,无论如何我都不需要ID块,所以YMMV


答案 2

不要对 Postgres 序列使用 GenerationType.SEQUENCE!

这完全违反直觉,但Hibernate的人完全搞砸了。您必须使用GenerationType.AUTO,或者如果您必须重新启动/重建数据库,则Hibernate将拆除您的序列。他们允许此代码进入生产构建几乎是刑事疏忽,但是Hibernate团队以其对完全错误位置的牛头立场而闻名(例如,查看他们在LEFT JOIN上的位置)。


推荐