使用 Hibernate 注释映射 PostgreSQL 串行类型
Posted
技术标签:
【中文标题】使用 Hibernate 注释映射 PostgreSQL 串行类型【英文标题】:Mapping PostgreSQL serial type with Hibernate annotations 【发布时间】: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 请修改选择的答案 - 我相信我的答案更正确,我个人必须不断回到这里来记住如何正确地做到这一点!每次我尝试使用不正确的答案,然后再进一步寻找自己的正确答案!
【参考方案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.INSERT
和GenerationType.IDENTITY
,但都没有阻止null
在更新的saveAll()
调用中插入。
帮助将该字段标记为不可写以进行休眠:
@Column(insertable = false, updatable = false)
private Integer orderId;
(感谢this answer)
【讨论】:
以上是关于使用 Hibernate 注释映射 PostgreSQL 串行类型的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 JPA/Hibernate 注释将 MySQL char(n) 列映射到实例变量?
如何使用 hibernate/jpa 注释将一个类映射到不同的表
Spring MVC“org.hibernate.PropertyAccessException”中的休眠注释映射异常
未能延迟初始化角色集合:无法初始化代理 - Hibernate 中的 @ManyToMany 映射注释中没有会话错误? [复制]