2. 标准命名策略

Hibernate 6 默认使用标准命名策略。它会根据实体名称和列名生成标准化的序列名称。例如,对于实体 Person 和列 id,序列名将是 person_seq

配置方式:在 application.properties 中添加以下配置:

spring.jpa.properties.hibernate.id.db_structure_naming_strategy=standard

来看一个基础实体类示例:

@Entity
public class Person {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String name;

    // setters and getters
}

使用标准策略时,Hibernate 会自动创建名为 person_seq 的序列:

Hibernate: 
  create table person (
    id bigint not null,
    name varchar(255),
    primary key (id)
  )
Hibernate: 
  create sequence person_seq start with 1 increment by 50

⚠️ 关键点:标准策略默认使用较大的增量值(如 50),这是为了优化批量操作,减少数据库调用次数。

插入记录时,Hibernate 会使用 person_seq 生成主键:

Hibernate: 
  select next value for person_seq
Hibernate: 
  insert 
    into person (name,id) 
    values (?,?)

自定义表名:可以通过 @Table 注解覆盖表映射,序列名会同步更新:

@Entity
@Table(name = "my_person_table")
public class Person {
    // ...
}

此时序列名变为 my_person_table_seq

Hibernate: 
  create table my_person_table (
    id bigint not null,
    name varchar(255),
    primary key (id)
  )
Hibernate: 
  create sequence my_person_table_seq start with 1 increment by 50

3. 遗留命名策略

此策略与标准策略类似,但使用遗留命名约定或生成器名称。默认情况下,所有实体共享名为 hibernate_sequence 的序列

配置方式

spring.jpa.properties.hibernate.id.db_structure_naming_strategy=legacy

使用 Person 实体时,Hibernate 会创建:

Hibernate: 
  create table person (
    id bigint not null,
    name varchar(255),
    primary key (id)
  )
Hibernate: 
  create sequence hibernate_sequence start with 1 increment by 1

与标准策略的区别:默认增量值为 1(而非 50),每次只递增 1。

插入记录时使用共享序列:

Hibernate: 
  select next value for hibernate_sequence
Hibernate: 
  insert 
    into person (name,id) 
    values (?,?)

自定义序列:即使使用 @Table 修改表名,序列名仍为 hibernate_sequence。但可通过 @SequenceGenerator 自定义:

@Id
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "person_custom_seq")
@SequenceGenerator(name = "person_custom_seq", sequenceName = "person_custom_seq", allocationSize = 10)
private Long id;

此时生成的序列名为 person_custom_seq,增量为 10:

Hibernate: 
  create sequence person_custom_seq start with 1 increment by 10

💡 适用场景:主要用于兼容旧版 Hibernate,避免破坏现有系统。

4. 单一命名策略

Hibernate 6 新增此策略,为同一 schema 下的所有实体使用统一序列名(与遗留策略类似,所有实体共享 hibernate_sequence)。

配置方式

spring.jpa.properties.hibernate.id.db_structure_naming_strategy=single

考虑两个实体 PersonBook

@Entity
public class Book {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    private Long id;
    private String title;

    // setters and getters
}

Hibernate 只创建一个共享序列:

Hibernate: 
  create table book (...)
Hibernate: 
  create table person (...)
Hibernate: 
  create sequence hibernate_sequence start with 1 increment by 1

插入记录验证

Person person = new Person();
person.setName("John Doe");
personRepository.save(person);

Book book = new Book();
book.setTitle("Baeldung");
bookRepository.save(book);

List<Person> personList = personRepository.findAll();
List<Book> bookList = bookRepository.findAll();

assertEquals((long)1,(long) personList.get(0).getId());
assertEquals((long)2, (long) bookList.get(0).getId());

✅ 结果:Person 获得 ID 1,Book 获得 ID 2,证明使用同一序列生成器。

5. 自定义命名策略

通过实现 ImplicitDatabaseObjectNamingStrategy 接口,可以完全自定义序列命名规则。

实现步骤

  1. 创建自定义策略类:

    public class CustomSequenceNamingStrategy implements ImplicitDatabaseObjectNamingStrategy {
     @Override
     public QualifiedName determineSequenceName(Identifier catalogName, Identifier schemaName, Map<?, ?> map, ServiceRegistry serviceRegistry) {
         JdbcEnvironment jdbcEnvironment = serviceRegistry.getService(JdbcEnvironment.class);
         String seqName = ((String) map.get("jpa_entity_name")).concat("_custom_seq");
         return new QualifiedSequenceName(
           catalogName,
           schemaName,
           jdbcEnvironment.getIdentifierHelper().toIdentifier(seqName));
     }
    
     // 其他方法...
    }
    
  2. 配置 Hibernate 使用自定义策略:

    spring.jpa.properties.hibernate.id.db_structure_naming_strategy=com.example.CustomSequenceNamingStrategy
    

生成的序列名将遵循自定义规则(如 person_custom_seq):

Hibernate: 
  create sequence person_custom_seq start with 1 increment by 50

替代方案PhysicalNamingStrategy 可实现更全面的命名规则(不仅限于序列):

public class CustomPhysicalNamingStrategy extends DelegatingPhysicalNamingStrategy {
    @Override
    public Identifier toPhysicalSequenceName(Identifier name, JdbcEnvironment context) {
        return new Identifier(name.getText() + "_custom_seq", name.isQuoted());
    }

    // 其他表/列命名方法...
}

6. 总结

本文详细探讨了 Hibernate 6 的序列命名策略:

  • 标准策略:基于实体名生成序列(如 person_seq),默认增量 50
  • 遗留策略:所有实体共享 hibernate_sequence,增量 1,兼容旧版
  • 单一策略:类似遗留策略,统一使用 hibernate_sequence
  • 自定义策略:通过 ImplicitDatabaseObjectNamingStrategyPhysicalNamingStrategy 实现完全控制

💡 踩坑提示:升级 Hibernate 6 时,默认策略变更可能导致序列名冲突,建议显式配置策略。

完整示例代码可在 GitHub 获取。


原始标题:Sequence Naming Strategies in Hibernate 6 | Baeldung