【问题标题】:Hibernate generating two different sequence Ids for PostgreSQL insertHibernate 为 PostgreSQL 插入生成两个不同的序列 ID
【发布时间】:2011-06-04 07:30:59
【问题描述】:

我有一个使用序列生成的主键定义的实体:

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

我使用的是 PostgreSQL,并且这个键被定义为一个序列号。根据PostgreSQL

select last_value from id_key_seq;

返回

1603.

当我执行 create() 来保存该实体的实例时,我在日志中看到以下内容(已删除不相关的内容):


05 15:15:26.948 org.hibernate.id.enhanced.SequenceStructure [DEBUG] - 获得的序列值:1604

05 15:15:26.948 org.hibernate.event.def.AbstractSaveEventListener [DEBUG] - 生成标识符:1554,使用策略:org.hibernate.id.enhanced.SequenceStyleGenerator


随后的 SQL 插入语句引用值 1554,而不是它应该使用的值,1604(基于从 SequenceStructure 返回的值。Hibernate 从哪里得到 1554?

在我看来,Hibernate 在这里有一个错误 - SequenceStructure 知道正确的下一个值,但它没有被使用。知道如何解决这个问题吗?

仅供参考:我知道this page, which says to use GenerationType.AUTO,因为“Hibernate 的人完全把这搞砸了”,但除了那个不太有用的声明之外,没有太多其他的东西。

【问题讨论】:

    标签: hibernate postgresql sequence generated


    【解决方案1】:

    看起来如果您使用 GenerationType.SEQUENCE,您需要将“增量值”指定为 1 以避免将序列用作 Hi/Lo 种子。

    您发布的问题的第一个答案(有用的答案)说明您需要在 @GeneratedValue 注释中指定“allocationSize=1”。

    在较新的 Hibernate 版本中,您可以改为在 Hibernate 属性中设置 hibernate.id.new_generator_mappings=true;见the docs

    【讨论】:

    • 感谢@araqnid,将 allocationSize 设置为 1 确实有效,但我很好奇这种方法不是“好的做法”的评论。
    • 将 allocationSize 设置为 1 是一种退化的情况,使得 HiLo 样式的生成器可以作为正常的序列生成器工作。 OTOH,这是你需要的,所以使用它。查看 Hibernate 3.5 中的代码,分配大小用于选择优化器实现,因此现在处理得很好。
    • 在我看来,Hibernate 团队需要重新考虑他们的实现;这令人困惑且不必要。将 allocationSize 设置为 1 正是我所需要的,但我想知道这是否不应该是 PostgreSQL 上 SEQUENCE 的默认值。
    • 最好设置hibernate.id.new_generator_mappings,这会让一切都更加理智。
    猜你喜欢
    • 1970-01-01
    • 2016-04-04
    • 2022-09-27
    • 2013-02-26
    • 1970-01-01
    • 1970-01-01
    • 2011-07-30
    • 2016-12-05
    • 2018-10-12
    相关资源
    最近更新 更多