31

我已将 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?

谢谢你。

4

4 回答 4

42

我有同样的问题。这与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;
}

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

更新:我最终使用了allocationSize = 1,并且事情似乎按我的预期工作。我的应用程序是这样的,所以我真的不需要 ID 块,所以YMMV

于 2010-11-26T22:27:28.470 回答
31

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

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

于 2010-12-21T17:21:33.043 回答
9

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

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

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

  1. GenerationType.AUTO -> 被视为 GenerationType.SEQUENCE
  2. GenerationType.SEQUENCE -> 映射到博客中讨论的 org.hibernate.id.enhanced.SequenceStyleGenerator 类
  3. GenerationType.TABLE -> 映射到博客中讨论的 org.hibernate.id.enhanced.TableGenerator 类
于 2011-12-05T20:36:06.333 回答
0

在 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;

大多数使用大写名称的 Hibernate 需要传递转义引号才能理解 Postgres 并找到表、列或序列名称。

于 2012-10-03T15:43:09.647 回答