1. Introduction

In this tutorial, we’ll explore how to configure Hibernate 6’s implicit naming strategies for database sequences. Hibernate 6 introduces several new naming strategies that affect how sequences are named and used.

2. Standard Naming Strategy

By default, Hibernate 6 uses the standard naming strategy. It uses a standard naming convention to generate sequence names based on the entity name and the column name. For example, if we have an entity Person with a column id, the sequence name would be person_seq.

To use the standard naming strategy, we need to add the necessary configurations in application.properties for different naming strategies. Here’s how to set up the configuration for each naming strategy:

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

Let’s look at a basic Person entity class to illustrate the naming convention:

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

    // setters and getters
}

In this example, since we’re using the standard strategy, Hibernate automatically generates a sequence named person_seq alongside the table creation:

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

One key point about the standard strategy is its default increment value. Hibernate assigns a larger value like 50 to optimize batch operations, reducing the number of database calls needed for sequence retrieval.

When we insert a Person record, Hibernate uses the person_seq sequence to generate the primary key:

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

In addition, we can override the table mapping by using the @Table annotation. This allows us to specify a custom table name that is then used to generate the corresponding sequence name.

For example, if we have an entity Person with a column id, we can specify a custom table name my_person_table to generate the sequence name my_person_table_seq:

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

In this case, the table name is my_person_table, and the generated sequence name is 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

When we attempt to insert a Person record, Hibernate utilizes the my_person_table_seq to generate the primary key value:

Hibernate: 
  select
    next value for my_person_table_seq

3. Legacy Naming Strategy

This strategy is similar to the standard strategy, but it uses a legacy naming convention or the generator name if specified to generate sequence names. For example, if we have an entity Person with a column id, the sequence name would be hibernate_sequence. Moreover, the hibernate_sequence sequence is used across all entities.

To enable the legacy strategy, we set the property hibernate.id.db_structure_naming_strategy to legacy in our application.properties file:

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

Let’s consider our existing Person entity class using the legacy strategy. In this scenario, Hibernate creates the table and a single sequence named hibernate_sequence with the same table name:

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

In contrast with the standard naming strategy, when using the legacy naming strategy, the default increment value for sequences is usually 1. This means that each new value generated by the sequence will be incremented by 1. 

When inserting a Person record, Hibernate relies on hibernate_sequence to generate the primary key:

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

Even with the legacy strategy, we can customize table names using the @Table annotation. In such cases, the generated sequence name won’t reflect the table name.

However, we can specify a custom sequence name by using the @SequenceGenerator annotation. This is particularly useful for managing sequences for specific entities:

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

In this example, we use the @SequenceGenerator annotation to specify a custom sequence name person_custom_seq with an allocation size of 10. The @GeneratedValue annotation is set to use this sequence generator:

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

When a Person record is inserted, Hibernate retrieves the next available value from the person_custom_seq sequence by executing the following SQL statement:

Hibernate: 
  select next value for person_custom_seq

The legacy strategy is primarily designed to maintain compatibility with older versions of Hibernate and to avoid breaking existing systems.

4. Single Naming Strategy

Hibernate 6 introduces the single naming strategy to simplify sequence naming by using a unified sequence name for all entities within the same schema. Similar to the legacy strategy, when using the single naming strategy, Hibernate generates a single sequence named hibernate_sequence that is shared among all entities in the schema.

This can be particularly useful for ensuring a consistent approach to sequence management. Let’s see how this works with two different entities: Person and Book.

To use the single naming strategy, we need to configure it in the application.properties file:

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

Here, we’ll create two entities, Person and Book, using the single naming strategy:

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

    // setters and getters
}

When using the single naming strategy, Hibernate generates a single sequence for all entities. Here’s how the SQL statements for the entities might look:

Hibernate: 
  create table book (
    id bigint not null,
    title varchar(255),
    primary key (id)
  )
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

Here we see only one sequence hibernate_sequence is created. Therefore, when inserting records into the Person and Book tables, Hibernate uses the hibernate_sequence sequence to generate the primary key values:

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());

In this example, we create and save two entities: Person and Book. Both entities should use the same sequence generator to generate primary keys. When we save the Person first and then the Book, the Person should get ID 1, and the Book should get ID 2.

5. Custom Naming Strategy

Moreover, we can also define our own sequence naming conventions through custom naming strategies. To use a custom naming strategy for sequences, we first need to create a custom implementation of ImplicitDatabaseObjectNamingStrategy. This interface is used to provide custom naming strategies for various database objects, including sequences.

Here’s how we can create a custom implementation of ImplicitDatabaseObjectNamingStrategy to customize sequence names:

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));
    }

    // others methods
}

In the determineSequenceName() method, we customize the generation of sequence names. First, we use the JdbcEnvironment service to access various database-related utilities, which helps us manage database object names efficiently. We then create a custom sequence name by appending a _custom_seq suffix to the entity name. This approach allows us to control the sequence name format across our database schema.

Next, we need to configure Hibernate to use our custom naming strategy:

spring.jpa.properties.hibernate.id.db_structure_naming_strategy=com.baeldung.sequencenaming.CustomSequenceNamingStrategy

With the custom ImplicitDatabaseObjectNamingStrategy, Hibernate generates SQL statements with the custom sequence names we defined:

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

In addition to ImplicitDatabaseObjectNamingStrategy, we can use PhysicalNamingStrategy which defines comprehensive naming conventions across all database objects. With PhysicalNamingStrategy, we’re able to implement complex naming rules that apply not just to sequences but to other database objects as well.

Here’s an example of how to implement custom sequence naming using PhysicalNamingStrategy:

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

    // other methods for tables and columns
}

6. Conclusion

In this article, we’ve explored how to use a custom naming strategy in Hibernate 6. The standard strategy generates sequence names based on entity names, while legacy and single strategies simplify sequence management by using a unified sequence name. Additionally, the custom naming strategy allows us to tailor sequence naming conventions.

As always, the source code for the examples is available over on GitHub.