Java Hibernate使用PostgreSQL序列不影响序列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/4288740/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-14 15:25:45  来源:igfitidea点击:

Hibernate use of PostgreSQL sequence does not affect sequence table

javahibernatepostgresqlormhibernate-mapping

提问by forker

I've configured Hibernate to use PostgreSQL sequence (via annotations) to generate values for primary key idcolumn as follows:

我已将 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;
}

What I see with this configuration is that hibernate is already assigning idvalues > 3000 on persisting, whereas the query on used sequence shows the following:

我在这个配置中看到的是,hibernate 已经在持久化时分配了大于 3000 的id值,而对使用序列的查询显示如下:

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

(1 row)

(1 行)

Questions:
Is there anything wrong or not?
Should hibernate sync with the sequence table?
If not, where does it store the last generated id?

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

Thank you.

谢谢你。

采纳答案by Nofate

I had the same problem. It is related to the id allocating strategies of Hibernate. Whe n you choose GenerationType.SEQUENCE, Hibernate uses HiLo strategy which allocates IDs in blocks of 50 by default. So you can explicitly set allocationSizevalue like this:

我有同样的问题。这与Hibernate的id分配策略有关。当您选择GenerationType.SEQUENCE 时,Hibernate 使用 HiLo 策略,默认情况下以 50 个块为单位分配 ID。所以你可以像这样显式设置allocationSize值:

@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;
}

Though, I've also heard opinions that using HiLo strategy with allocationSize=1is not a good practice. Some people recommend to use GenerationType.AUTOinstead when you have to deal with database-managed sequences

不过,我也听说过在allocationSize=1 的情况下使用 HiLo 策略并不是一个好的做法。当您必须处理数据库管理的序列时,有些人建议改用GenerationType.AUTO

Update:I did end up going with allocationSize=1, and things seem to work as I expect now. My application is such that I don't really need blocks of IDs anyway, so YMMV.

更新:我确实最终使用了 allocationSize=1,而且现在一切似乎都如我所愿。我的应用程序是这样的,反正我真的不需要 ID 块,所以YMMV.

回答by Matt Brock

DO NOT USE GenerationType.SEQUENCE for Postgres sequences!

不要将 GenerationType.SEQUENCE 用于 Postgres 序列!

It's completely counter-intuitive, but the Hibernate folks completely messed up on this. You must use GenerationType.AUTOor Hibernate will demolishyour sequences if you have to restart/rebuild your DB. It's almost criminally negligent that they would allow this code to go into a production build, but the Hibernate team is rather famous for their bull-headed stances towards flatly-wrong positions (check out their position on LEFT JOINs, for instance).

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

回答by Steve Ebersole

First, you have to determine which version of Hibernate you are using. In terms of hibernate-core versions, 3.2 onwards introduced more consistent support for id generators especially in regards to defined in annotations. See http://in.relation.to/Bloggers/New323HibernateIdentifierGeneratorsfor a discussion.

首先,您必须确定您使用的是哪个版本的 Hibernate。在 hibernate-core 版本方面,3.2 以后引入了对 id 生成器的更一致的支持,尤其是在注释中定义的。有关讨论,请参阅http://in.relation.to/Bloggers/New323HibernateIdentifierGenerators

Next 3.6 introduced a setting ('hibernate.id.new_generator_mappings') which makes the generators discussed in that blog the default way JPA-annotations are handled. The setting is false by default because Hibernate has to maintain backwards compatibility with older versions. If you want the new behavior (which is completely recommended) then simply set that setting to true.

Next 3.6 引入了一个设置('hibernate.id.new_generator_mappings'),它使该博客中讨论的生成器成为处理 JPA 注释的默认方式。该设置默认为 false,因为 Hibernate 必须保持与旧版本的向后兼容性。如果您想要新行为(完全推荐),只需将该设置设置为 true。

How GenerationType is handled depends on which version you are using and whether you have 'hibernate.id.new_generator_mappings' set to true. I will assume you are using 3.6+ (since anything older is, well, old) and do have 'hibernate.id.new_generator_mappings' set to true (since that is the recommendation for new apps):

GenerationType 的处理方式取决于您使用的版本以及您是否将 'hibernate.id.new_generator_mappings' 设置为 true。我假设您使用的是 3.6+(因为任何旧的东西都是旧的)并且确实将 'hibernate.id.new_generator_mappings' 设置为 true(因为这是对新应用程序的推荐):

  1. GenerationType.AUTO -> treated as GenerationType.SEQUENCE
  2. GenerationType.SEQUENCE -> maps to the org.hibernate.id.enhanced.SequenceStyleGenerator class discussed in the blog
  3. GenerationType.TABLE -> maps to the org.hibernate.id.enhanced.TableGenerator class discussed in the blog
  1. GenerationType.AUTO -> 视为 GenerationType.SEQUENCE
  2. GenerationType.SEQUENCE -> 映射到博客中讨论的 org.hibernate.id.enhanced.SequenceStyleGenerator 类
  3. GenerationType.TABLE -> 映射到博客中讨论的 org.hibernate.id.enhanced.TableGenerator 类

回答by Christian Vielma

In Postgres I would do this:

在 Postgres 我会这样做:

@Id 
@SequenceGenerator(name="pk_sequence",sequenceName="\"entity_id_seq\"")
@GeneratedValue(strategy=GenerationType.SEQUENCE,generator="\"pk_sequence\"")
@Column(name="\"id\"", unique=true)
private int id;

Mostly with uppercase names Hibernate need to be passed escaped quotes in order to understand Postgres and find the tables, columns or sequences names.

大多数情况下使用大写名称 Hibernate 需要传递转义引号以便理解 Postgres 并找到表、列或序列名称。