mysql - 让 Hibernate 尊重 MySQL 和 PostgreSQL 中的序列

标签 mysql hibernate postgresql

我正在开发一个现有的应用程序,它使用 Hibernate 和 MySQL 在数据库中存储对象。由于应用程序中的所有对象共享一个用于填充主键 id 列的 id 属性,因此最初的开发人员决定将 id在抽象父类(super class)中,像这样:

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 列创建的序列。这感觉非常危险和 splinter 。

最佳答案

为了使 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 脚本在数据库之间有所不同。

关于mysql - 让 Hibernate 尊重 MySQL 和 PostgreSQL 中的序列,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29492064/

相关文章:

sql - 使用 GIN 索引进行 Postgres 文本搜索并在其他列上对 DESC 进行排序

sql - Node.js 和 Postgres : Temporary table "relation does not exist" on chained query

MySql 从一次选择中设置多个变量

mysql - Drupal 8 数据库安装未连接到 docker mysql 容器

mysql - 如何: Find and update all the entries where the value in one column shows up more than once

java - 从父级 JPA 获取所有子级和子级

sql - 如何在同一查询但不同列中将 2 个查询合并在一起?

php : Avoid database queries for each visitors

java - 我需要在 Google 应用引擎中使用 JPA 提供程序吗?

java - 使用 Spring + hibernate + JPA 从表中选择特定列并将结果存储到非实体 POJO