Oracle Sequence Increment Size and Hibernate: How to Fix ID Generation Mismatches in Spring Boot

When developing a Spring Boot application with Hibernate/JPA and an Oracle database, sequence-based primary key generation is a common approach. However, application upgrades, Hibernate configuration changes, or database migrations can expose differences between the sequence configuration expected by Hibernate and the sequence actually defined in Oracle.

One particularly common startup error is:

org.hibernate.MappingException:
The increment size of the [ENTITY_SEQ] sequence is set to [50]
in the entity mapping while the associated database sequence
increment size is [1]

This article explains why this happens, how Oracle sequences interact with Hibernate’s @SequenceGenerator, how to correct the configuration, and how to manage the change safely with Liquibase.


Understanding Oracle Sequences

An Oracle sequence is a database object used to generate unique numeric values.

A typical sequence might be created as follows:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 1
    MAXVALUE 9999999999999999999999999999
    NOCYCLE;

Applications can retrieve values using:

SELECT ENTITY_SEQ.NEXTVAL FROM DUAL;

Each request for NEXTVAL advances the sequence according to its INCREMENT BY configuration.

For example, with:

INCREMENT BY 1

the sequence produces values such as:

1
2
3
4
5
...

With:

INCREMENT BY 50

the database-level sequence values advance as:

1
51
101
151
201
...

However, when Hibernate uses sequence optimizers, these database sequence values may represent allocation boundaries rather than the exact IDs ultimately assigned to every entity.


Hibernate Sequence Generation

A JPA entity commonly maps an Oracle sequence using @SequenceGenerator:

@Entity
public class ExampleEntity {

    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE,
        generator = "entity_generator"
    )
    @SequenceGenerator(
        name = "entity_generator",
        sequenceName = "ENTITY_SEQ",
        allocationSize = 50
    )
    private Long id;
}

The important property is:

allocationSize = 50

This tells Hibernate how IDs should be allocated in conjunction with the database sequence and Hibernate’s sequence optimizer.

Using an allocation size greater than 1 can substantially reduce database round trips when inserting many records.


The Increment Size Mismatch Error

Suppose the entity contains:

@SequenceGenerator(
    name = "entity_generator",
    sequenceName = "ENTITY_SEQ",
    allocationSize = 50
)

while Oracle contains:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 1;

Hibernate may detect:

Hibernate allocation size: 50
Oracle sequence increment: 1

and fail during application initialization with an error similar to:

The increment size of the [ENTITY_SEQ] sequence is set to [50]
in the entity mapping while the associated database sequence
increment size is [1]

The problem is therefore not that Oracle cannot generate IDs. The problem is that the application’s sequence-generation configuration and the database sequence definition disagree.


Solution 1: Change the Oracle Sequence to INCREMENT BY 50

If the application’s intended allocation size is 50, modify the Oracle sequence accordingly.

For an existing sequence:

ALTER SEQUENCE ENTITY_SEQ
    INCREMENT BY 50;

If creating a new sequence:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 50
    MAXVALUE 9999999999999999999999999999
    NOCYCLE;

The JPA configuration then remains:

@SequenceGenerator(
    name = "entity_generator",
    sequenceName = "ENTITY_SEQ",
    allocationSize = 50
)

The two configurations now agree:

Hibernate allocationSize = 50
Oracle INCREMENT BY   = 50

This is generally appropriate when the application intentionally uses Hibernate’s pooled sequence allocation.


Solution 2: Change Hibernate to allocationSize = 1

Another option is to leave the Oracle sequence unchanged:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 1;

and change the entity:

@SequenceGenerator(
    name = "entity_generator",
    sequenceName = "ENTITY_SEQ",
    allocationSize = 1
)

The configurations then agree:

Hibernate allocationSize = 1
Oracle INCREMENT BY   = 1

This is straightforward, but it can increase database interaction because Hibernate cannot reserve IDs in larger allocation blocks.

For applications performing many inserts, an allocation size such as 50 can therefore provide better performance.


Why Hibernate Commonly Uses an Allocation Size of 50

Modern Hibernate/JPA applications frequently use allocation sizes greater than one to reduce calls to the database sequence.

Without pooling, generating many IDs can involve many sequence requests:

SELECT ENTITY_SEQ.NEXTVAL FROM DUAL;
SELECT ENTITY_SEQ.NEXTVAL FROM DUAL;
SELECT ENTITY_SEQ.NEXTVAL FROM DUAL;
...

With an appropriate pooled sequence strategy, Hibernate can obtain sequence allocation boundaries less frequently and generate IDs from the allocated range.

This becomes particularly useful for:

  • batch processing;
  • event processing;
  • high-volume inserts;
  • financial transaction processing;
  • audit records;
  • message ingestion;
  • scheduled import jobs.

The exact behavior depends on the Hibernate version and configured sequence optimizer, so allocationSize should not simply be interpreted as “Hibernate always executes one NEXTVAL and then blindly generates the next 49 numbers.” The optimizer determines how the allocated range is interpreted.


Checking an Existing Oracle Sequence

Before changing anything, inspect the current sequence configuration.

You can query:

SELECT
    SEQUENCE_NAME,
    MIN_VALUE,
    MAX_VALUE,
    INCREMENT_BY,
    CACHE_SIZE,
    LAST_NUMBER
FROM USER_SEQUENCES
WHERE SEQUENCE_NAME = 'ENTITY_SEQ';

The important column for this problem is:

INCREMENT_BY

If the result contains:

SEQUENCE_NAME   INCREMENT_BY
--------------  ------------
ENTITY_SEQ      1

while Hibernate expects:

allocationSize = 50

you have identified the mismatch.

After running:

ALTER SEQUENCE ENTITY_SEQ
    INCREMENT BY 50;

verify again:

SELECT
    SEQUENCE_NAME,
    INCREMENT_BY
FROM USER_SEQUENCES
WHERE SEQUENCE_NAME = 'ENTITY_SEQ';

The expected result is:

ENTITY_SEQ    50

Managing the Change with Liquibase

In production systems, database changes should generally be version-controlled rather than executed manually.

Liquibase can manage the sequence modification.

One simple changeset is:

<changeSet id="update-entity-sequence-increment" author="developer">
    <sql>
        ALTER SEQUENCE ENTITY_SEQ INCREMENT BY 50
    </sql>
</changeSet>

Alternatively, when supported by the Liquibase version in use, the sequence can be managed using Liquibase’s sequence changes.

For creation:

<changeSet id="create-entity-sequence" author="developer">
    <createSequence
        sequenceName="ENTITY_SEQ"
        startValue="1"
        incrementBy="50"/>
</changeSet>

This keeps the database definition aligned with the application’s JPA mapping.


Adding a Liquibase Rollback

For controlled deployments, consider providing rollback instructions.

For example:

<changeSet id="update-entity-sequence-increment" author="developer">

    <sql>
        ALTER SEQUENCE ENTITY_SEQ INCREMENT BY 50
    </sql>

    <rollback>
        ALTER SEQUENCE ENTITY_SEQ INCREMENT BY 1
    </rollback>

</changeSet>

This makes the intended previous configuration explicit.

However, changing a sequence’s increment does not reverse IDs that have already been allocated or generated. Rollback should therefore be considered a configuration rollback rather than a restoration of historical sequence values.


Be Careful When Changing Existing Production Sequences

Changing:

INCREMENT BY 1

to:

INCREMENT BY 50

does not reset the sequence.

For example, if the current sequence is already around:

10501

changing its increment affects subsequent calls; it does not automatically return the sequence to 1.

This is normally desirable because resetting a sequence associated with an existing table can create duplicate primary keys.

Before changing an active production sequence, inspect both the sequence and the existing IDs.

For example:

SELECT MAX(ID)
FROM EXAMPLE_TABLE;

and:

SELECT
    SEQUENCE_NAME,
    INCREMENT_BY,
    LAST_NUMBER
FROM USER_SEQUENCES
WHERE SEQUENCE_NAME = 'ENTITY_SEQ';

This helps identify potentially dangerous inconsistencies before deployment.


Sequence Cache vs Hibernate Allocation Size

Two concepts are sometimes confused:

Oracle CACHE

and:

Hibernate allocationSize

They solve different problems.

An Oracle sequence can be defined as:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 50
    CACHE 20;

CACHE 20 tells Oracle how many sequence values it should cache internally for efficient sequence generation.

Hibernate’s:

allocationSize = 50

controls how Hibernate allocates entity identifiers in conjunction with the sequence optimizer.

Therefore:

CACHE 20

does not mean the same thing as:

allocationSize = 20

They operate at different layers.


Why Gaps in IDs Are Normal

Sequence-generated primary keys should generally not be expected to be gapless.

You might see:

1001
1002
1003
1051
1052
...

This does not necessarily indicate data loss.

Gaps can occur because of:

  • transaction rollbacks;
  • application restarts;
  • Oracle sequence caching;
  • Hibernate allocation pools;
  • concurrent application instances;
  • failed transactions;
  • unused allocated identifiers.

Primary keys should normally guarantee uniqueness, not continuous numbering.

If a business process requires strictly sequential document numbers, invoice numbers, or regulatory identifiers, those values should usually be modeled separately from the technical database primary key.


Multiple Application Instances

Sequence allocation becomes particularly important in distributed systems.

Suppose several application instances are simultaneously writing to the same Oracle database:

Application instance A
Application instance B
Application instance C
        |
        v
     Oracle DB
        |
        v
    ENTITY_SEQ

A properly configured database sequence and Hibernate optimizer allow each instance to obtain unique identifier ranges safely.

This is one reason database sequences are preferable to application logic such as:

SELECT MAX(ID) + 1

The latter is unsafe under concurrency because two application instances can calculate the same next ID.


Avoid SELECT MAX(ID) + 1

A tempting alternative is:

SELECT MAX(ID) + 1
FROM EXAMPLE_TABLE;

This should generally not be used for primary key generation.

Consider two transactions running simultaneously:

Transaction A -> MAX(ID) = 100
Transaction B -> MAX(ID) = 100

Both calculate:

101

Both then attempt:

INSERT ... ID = 101

One transaction can fail with a primary key violation.

Oracle sequences are specifically designed to handle concurrent ID generation efficiently.


Recommended JPA Configuration

A typical configuration can look like:

@Entity
@Table(name = "EXAMPLE_TABLE")
public class ExampleEntity {

    @Id
    @GeneratedValue(
        strategy = GenerationType.SEQUENCE,
        generator = "entity_sequence_generator"
    )
    @SequenceGenerator(
        name = "entity_sequence_generator",
        sequenceName = "ENTITY_SEQ",
        allocationSize = 50
    )
    private Long id;
}

Corresponding Oracle configuration:

CREATE SEQUENCE ENTITY_SEQ
    START WITH 1
    INCREMENT BY 50
    MAXVALUE 9999999999999999999999999999
    NOCYCLE;

The key relationship is:

@SequenceGenerator(allocationSize = 50)
                    |
                    v
Oracle sequence INCREMENT BY 50

Keeping these values synchronized prevents Hibernate’s sequence validation error.


Troubleshooting Checklist

When encountering an error such as:

The increment size of the [ENTITY_SEQ] sequence is set to [50]
in the entity mapping while the associated database sequence
increment size is [1]

check the following:

  1. Find the entity’s sequence configuration:
@SequenceGenerator(
    sequenceName = "ENTITY_SEQ",
    allocationSize = 50
)
  1. Check the Oracle sequence:
SELECT
    SEQUENCE_NAME,
    INCREMENT_BY
FROM USER_SEQUENCES
WHERE SEQUENCE_NAME = 'ENTITY_SEQ';
  1. Compare the values.

If Hibernate has:

50

and Oracle has:

1

decide which configuration represents the intended behavior.

  1. Either change Oracle:
ALTER SEQUENCE ENTITY_SEQ
    INCREMENT BY 50;

or change Hibernate:

allocationSize = 1
  1. Restart the application and verify Hibernate starts successfully.
  2. Test inserts and confirm that generated IDs remain unique.
  3. In clustered environments, test simultaneous inserts from multiple application instances.

Conclusion

The Hibernate error:

The increment size of the sequence is set to [50]
in the entity mapping while the associated database sequence
increment size is [1]

is fundamentally a configuration mismatch between Hibernate’s identifier generator and the Oracle sequence.

If the application intentionally uses:

allocationSize = 50

the corresponding Oracle sequence can be configured with:

ALTER SEQUENCE ENTITY_SEQ
    INCREMENT BY 50;

If sequence pooling is not required, both sides can instead use an increment/allocation size of 1.

Whichever approach is selected, the important principle is consistency between the JPA mapping and database schema. In production environments, sequence changes should also be version-controlled through a migration tool such as Liquibase and verified against existing data before deployment.

Correctly configured Oracle sequences provide a concurrency-safe and highly efficient mechanism for primary key generation, while Hibernate’s allocation strategies can further reduce database overhead in high-throughput Java applications.

This article is inspired by real-world challenges we tackle in our projects. If you're looking for expert solutions or need a team to bring your idea to life,

Let's talk!

    Please fill your details, and we will contact you back

      Please fill your details, and we will contact you back