【问题标题】:Make Hibernate respect sequences in both MySQL and PostgreSQL在 MySQL 和 PostgreSQL 中使 Hibernate 尊重序列
【发布时间】:2015-06-12 01:52:14
【问题描述】:

我正在开发一个使用 Hibernate 和 MySQL 在数据库中存储对象的现有应用程序。由于应用程序中的所有对象共享一个id 属性,该属性用于填充主键id 列,因此最初的开发人员决定将id 放在一个抽象超类中,如下所示:

public abstract class BaseModel implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    @Column(name = "ID")
    private Long id;
}

现在,系统中每个继承自BaseModel 的类都获得了id 属性,Hibernate 会将它整齐地存储在数据库中。到目前为止一切顺利。

该项目目前在其 maven 依赖项中使用 Hibernate 4.3.5.Final:

<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-entitymanager</artifactId>
    <version>4.3.5.Final</version>
</dependency>

需要更改此应用程序才能在 MySQL 和 PostgreSQL 上运行。

我遇到了一个问题,即 Hibernate 不尊重 PostgreSQL 中的 id/auto increment 列。当我在数据库中手动插入一行时,PostgreSQL 会插入该行并更新序列。之后我启动应用程序时,Hibernate 会尝试插入 id 为“1”的行,从而有效地忽略 PostgreSQL 序列。

据我所知,为了解决这个问题,我必须告诉 Hibernate 使用具有特定数据库序列的序列生成器,如下所示:

public abstract class BaseModel implements Serializable {
    @Id 
    @SequenceGenerator(name="pk_sequence",sequenceName="entity_id_seq", allocationSize=1)
    @GeneratedValue(strategy=GenerationType.SEQUENCE,generator="pk_sequence")
    @Column(name = "ID")
    private Long id;
}

这个解决方案有两个问题(按重要性排序):

  1. 当新版本的应用程序针对现有的 MySQL 数据库运行时,这会破坏一些东西。
  2. 这需要我将 id 列“下推”到类层次结构中,并显式管理所有类和表的所有序列,结果证明这是一件苦差事。

第一点可以通过@TableGenerator 注释来解决,我现在正在研究它,但它仍然需要我进行大量重构。有没有更好/更智能的方法来告诉 Hibernate 在应用程序启动时初始化和尊重数据库中现有记录的现有序列或 id?

其他研究: 我注意到应用程序创建了一个名为 hibernate_sequence 的序列,并忽略了 PostgreSQL 为 serial id 列创建的序列。这感觉非常危险和破碎。

【问题讨论】:

  • 您使用的是什么 Hibernate 版本?在各种版本中,Hibernate 的序列生成似乎发生了一些重大变化,但我没有找到太多关于它的文档。
  • 4.3.5.Final,我在问题中添加了该信息,感谢您指出遗漏。
  • 我同意你的“危险和破碎”的观点。它还使用 50 的分配大小而不是 PostgreSQL 默认的 1,但这是 JPA 规范的错误。 Hibernate 期望拥有 db,除非它的配置被覆盖,否则它不会与其他人一起玩得很好。

标签: mysql hibernate postgresql


【解决方案1】:

为了使 Hibernate 与 MySQL 和 PostgreSQL 兼容,我将 PostgreSQL 版本数据库中的 SERIAL 列更改为 BIGINT。 Hibernate 使用提到的hibernate_sequence 为新插入的行生成 id。

这样做的缺点是开发者在 MySQL 和 PostgreSQL 之间切换时需要了解以下区别:

  • 在 MySQL 上,Hibernate 使用表定义中的自动递增列,从而产生每个表唯一的 ID。
  • 在 PostgreSQL 上,Hibernate 使用它的 hibernate_sequence 为所有表生成 id,使 id 在所有表中都是唯一的,并导致表中行的 id 间隔更大。

此解决方案使我能够在 MySQL 和 PostgreSQL 上使用相同的 Java 代码。只有用于创建/更改表定义的 DDL 脚本在数据库之间有所不同。

【讨论】:

    猜你喜欢
    • 2011-06-28
    • 2018-09-14
    • 1970-01-01
    • 2021-06-07
    • 2011-05-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多