SQL序列: Hibernate和Liquibase

5
我很新于数据库开发,也许这个问题不是完全准确的,但如果有人能使它更加清晰,我会非常感激...我已经阅读了所有关于序列的内容,以及如何优先使用序列而不是标识。我有一个假设性的问题。如果我要使用序列来生成我的PK,并使用Hibernate(数据插入)和Liquibase(模式创建),那么定义序列的正确位置是什么?
例如:在类级别上生成序列。
@Entity
@Table(name = "USER")
public class User {

    @Id
    @SequenceGenerator(name = "USER_SEQ", sequenceName = "USER_SEQ")
    @GeneratedValue(strategy = SEQUENCE, generator = "USER_SEQ")
    @Column(name = "ID")
    private Long id;

    // other fields
}

另一个例子:在模式层面上生成序列。

changelog.xml

<changeSet author="wesleyy">
    <createSequence catalogName="cat"
            cycle="true"
            incrementBy="1"
            maxValue="1000"
            minValue="10"
            ordered="true"
            schemaName="public"
            sequenceName="user_seq"
            startValue="1"/>
</changeSet>

在Liquibase和Hibernate中都需要定义序列吗?这两者之间到底有什么区别?

3个回答

3
如果您希望id主键自动生成,那么可以使用JPA实现(如Hibernate或其他)来简单完成,具体操作如下:
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private long id;

主键 Id 将自动生成并由系统进行管理。

使用 Liquibase,在您的基本 changelog XML 文件中,只要您的数据库支持自动生成的 ID(许多数据库都支持此功能,请确认一下),您可以执行以下操作:

  <changeSet author="name" id="auto increment example">
    <createTable tableName="users">
        <column autoIncrement="true" name="id" type="SERIAL">
            <constraints primaryKey="true" primaryKeyName="users_pkey"/>
        </column>
        <column name="some_other_column" type="VARCHAR(255)"/>
        <column name="another_column" type="VARCHAR(255)"/>
    </createTable>
</changeSet>

是的,但我明确询问序列概念,而不仅仅是顺序ID生成。序列在数据库中内部是另一个表,可以实现更好的性能。 - wesleyy
2
使用GenerationType.IDENTITY时要小心,因为它会禁用批处理功能。如果您关心性能并需要大量的行,请注意。例如,请参见 https://thorben-janssen.com/hibernate-tips-use-custom-sequence/。 - Guillermo

3
通过类中的User
@SequenceGenerator(name = "USER_SEQ", sequenceName = "USER_SEQ")
@GeneratedValue(strategy = SEQUENCE, generator = "USER_SEQ")

您要告诉Hibernate:对于每个插入到数据库中的User对象,从名为USER_SEQ的序列中获取新的主键值。

通过将描述的changeSet添加到Liquibase XML脚本中,您告诉Liquibase:如果该changeSet尚未应用于数据库,则下次在数据库中创建名为user_seq的序列。

换句话说,在Liquibase脚本中,您创建序列,并在User类的代码中使用它。


有一件事我不确定:如果我在Liquibase中没有明确定义,Hibernate是否会自动创建序列?或者如果我想使用序列,我必须在两个地方都定义它吗? - wesleyy
有时这样的序列是自动生成的,例如在Postgresql中用于自增字段。这是特定于数据库的。 - Anton Tupy

0

你的问题有点误导性,因为它涉及到两个不同的事情:

  • 实体标识符的生成(应用程序的行为)和
  • 底层数据库模式的定义。

“如果我要使用序列来生成我的PK,并且使用Hibernate(数据插入)和Liquibase(模式创建),那么定义序列的正确位置是什么?”

你可以以许多不同的方式定义序列。它总是以SQL语句结束,但有时你可能更喜欢使用Liquibase、Flyway或Hibernate进行DDL自动导出(Hibernate hbm2ddl.auto possible values and what they do?)。

我个人偏好于在初始开发期间依赖于Hibernate自动模式导出,然后使用一些提到的基于版本的DB迁移工具。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接