在 JPA 中以 @GeneratedValue 作为 Sequence 生成主键,但使用外部数据库访问使其工作

Generate primary key with @GeneratedValue in JPA as Sequence, but make it work using external Database Access

提问人:Tim Lammarsch 提问时间:8/6/2022 最后编辑:MWiesnerTim Lammarsch 更新时间:8/7/2022 访问量:436

问:

我正在使用 PostgreSQL 12.11、JPA 3.1.0 和 Hibernate 5.6.10。我不想过分说明问题,但某些方面可能取决于实现。

我想生成一个以自动生成的 id 值作为主键的表,该表应该从 JPA 自动生成,但它也应该可以通过外部工具访问。BIGINT

  1. 如果我在 JPA 中使用 @GeneratedValue(即使使用 GenerationType.SEQUENCE), 不会设置数据库的默认值列注,因此 PostgreSQL 特定的 ID 生成不会不起作用。

  2. 如果我在 JPA 中使用 @GeneratedValue 和 columnDefinition = “BIGSERIAL”,则始终会有两个序列,即使指定 适当的名称,我很确定这将创建 相互冲突的价值观。(不过,我还没有测试过。

  3. 如果我根本不使用 @GeneratedValue,但 columnDefinition = “BIGSERIAL”,我将能够使用其他工具插入,但不能使用 JPA,其中 id 将始终为 0。

  4. 如果我使用 @GeneratedValue 并使用 columnDefinition 手动将默认值设置为序列的 nextval 调用,它将 生成时失败,因为当时序列不存在。

我现在正在做的是使用变体 1。对于外部访问,我手动将 id 设置为 nextval 的结果。这并不完美。对于 COPY,我什至需要一个 TEMPORARY TABLE。有没有一些“最佳方法”应该这样做?

PostgreSQL 休眠 JPA 序列

评论

0赞 MWiesner 8/6/2022
PostgreSQL 10+ 支持 IDENTITY 作为 GeneratedValue 策略,在后台使用 Serial/BigSerial。这对你来说是一个选择吗?这样,场景 2 就不会受到两个分离的 PK 生成器的影响。

答:

0赞 Tim Lammarsch 8/7/2022 #1

多亏了@MWiesner,我可以解决这个问题(比较上面的评论):

看起来,我的问题是 10+ 版之前与 PostgreSQL 更大的兼容性问题的一部分。从那时起,可以(并推荐)使用 GenerationType.IDENTITY。

通过研究这一点,我还了解到 PostgreSQL 10+ IDENTITY 在后台用作序列 - 这很重要,因为许多较旧的网站因为性能问题而不鼓励 IDENTITY。AFAICS 对于这个较新的实现来说,情况并非如此。

所以我现在正在做的是使用 GenerationType.IDENTITY,一切正常。

更多琐事:

  • 对于上面提到的版本,GenerationType.AUTO 默认为 SEQUENCE,而不是 IDENTITY。
  • JPA 将 PostgreSQL 配置设置为“默认生成为标识”,而不是“始终作为标识生成”。根据具体情况,这可能较差。我还没有找到如何改变它。