【问题标题】:Mapping PostgreSQL serial type with Hibernate annotations使用 Hibernate 注释映射 PostgreSQL 串行类型
【发布时间】:2011-06-26 04:05:12
【问题描述】:

我正在使用 Hibernate 3.3 和 PostgreSQL 8.x,并希望使用 Hibernate 注释来映射不是主键的自动递增列。

列是否使用 SERIAL 类型或 Postgres 中的序列映射无关紧要,只要它由数据库而不是 Hibernate 自动递增。我尝试了以下映射,但它们总是生成 null orderId。

@Column(name = "orderId", insertable = false)
@Generated(GenerationTime.INSERT)
//@GeneratedValue(strategy = javax.persistence.GenerationType.AUTO)
private Integer orderId;

我将不胜感激。

谢谢

【问题讨论】:

  • 你确定是null?你是怎么确定的?
  • 我写了一个集成测试并在调试器中检查了这个字段的值。
  • @alecswan 请修改选择的答案 - 我相信我的答案更正确,我个人必须不断回到这里来记住如何正确地做到这一点!每次我尝试使用不正确的答案,然后再进一步寻找自己的正确答案!

标签: hibernate postgresql sequence auto-increment


【解决方案1】:

以下映射应该可以正常工作:

@Column(name = "orderId")
@Generated(GenerationTime.INSERT)
private Integer orderId;

但是请注意,在刷新会话之前,新保存的对象的生成值不可用。

编辑:请注意,此映射不影响不会使 Hibernate 在模式生成期间创建类型为 serial 的列,因为 Hibernate 对值的性质一无所知在数据库端生成。因此,如果您希望 Hibernate 创建具有正确类型的列,则需要明确指定它:

@Column(name = "orderId", columnDefinition = "serial")
@Generated(GenerationTime.INSERT)
private Integer orderId;

在最近的 Hibernate 版本 (4.3) 上,您可以使用这个:

@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)
private Long orderId;

【讨论】:

  • 在加载对象之前刷新会话不起作用。我注意到 Hibernate 只是在 Postgres 数据库中生成类型为 INTEGER 的 orderid 列。如果类型不是 SERIAL 并且 Hibernate 不会生成任何会更新此列的触发器,我根本看不到这将如何工作。还有其他想法吗?谢谢
  • @alecswan:已更新。此外,刷新与保存对象的会话有关,而不是与加载对象的会话有关。
  • 在我的例子中,对象是在同一个会话中保存和加载的。添加 columnDefinition = "serial" 解决了问题,谢谢!是否有解决方案,例如使用身份生成器,使此解决方案也适用于其他数据库?
  • @alecswan:据我所知,Hibernate 不支持非 id 属性的生成器。
  • 投票,因为这可用于在非 id 列上生成值。这可能是一个大问题。这使得休眠特定(而不是 JPA)和数据库特定(PostgreSQL)的缺点变得容易。就我而言,这不是问题。
【解决方案2】:

接受的答案对我不起作用。

尽管如此:

@Id
@Column(name = "your_id", columnDefinition = "serial")
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer yourId;

【讨论】:

  • 这也是 JPA 不兼容的奖励。
  • 兼容怎么加分?
  • 为我工作,没有columnDefinition = "serial",我更喜欢只在 SQL 生成文件中声明它,使用 flyway(或 liquibase)
  • 等等,OP不是说他的列不是主键吗? @Id 注释在这种情况下是否仍然适用?
  • @Klesun 我一定错过了这个要求 - 哎呀
【解决方案3】:

我将它与 postgresql9.1 一起使用,也应该与 8 一起使用:

@SequenceGenerator(allocationSize=1, initialValue=1, sequenceName="account_id_seq", name="account_id_seq")
@GeneratedValue(generator="account_id_seq", strategy=GenerationType.SEQUENCE)
@Id
@Column(name="id")
private Integer id;

【讨论】:

  • 你也可以使用strategy=GenerationType.IDENTITY
  • 没有@Id 是否可以工作? (因为问题是明确的字段不是 id 字段)
  • 这个^是JPA注解版本,谢谢!
【解决方案4】:

数据库序列与您的私钥不同步。所以需要更新序列索引。

从 db 检查您的序列 id 并执行此 sql 命令。 (不要忘记备份你的数据库以防万一)

SELECT setval('your_primary_key_sequence', (SELECT MAX(your_primary_key) FROM your_table)+1);

【讨论】:

    【解决方案5】:

    我尝试了GenerationTime.INSERTGenerationType.IDENTITY,但都没有阻止null 在更新的saveAll() 调用中插入。

    帮助将该字段标记为不可写以进行休眠:

    @Column(insertable = false, updatable = false)
    private Integer orderId;
    

    (感谢this answer

    【讨论】:

      猜你喜欢
      • 2011-01-12
      • 2010-10-22
      • 2012-12-23
      • 2023-03-22
      • 2013-11-25
      • 1970-01-01
      • 2015-03-09
      • 1970-01-01
      • 2015-08-20
      相关资源
      最近更新 更多