Skip to content

Default to the pooled-lo optimizer in Hibernate ORM #31899

@yrodiere

Description

@yrodiere

Description

To be considered for Quarkus 3 as a way to address the infamous backwards-incompatible sequence changes in Hibernate ORM (see #31521)

Hibernate ORM defaults to the pooled optimizer, which assumes the pool of IDs it can use is between <sequence value >-<increment size>+1 and <sequence value>.

It works, but has a significant downside: every time you restart a sequence manually (native SQL, import script) you have to take care to set the value to max(id) + <increment size>, otherwise Hibernate ORM will use incorrect IDs. E.g. if you your max id is 2 and you restart your sequence to 3, next time Hibernate ORM retrieves the sequence value it will assign IDs between 3-<increment size>+1 and 3, which, with the default increment size of 50, leads to Hibernate ORM starting with negative IDs (-46, -47, ...) and eventually coming all the way back to already assigned IDs, i.e. 1, 2.

So, that can be surprising, and hence it's not a great default.

Hibernate ORM provides another optimizer, pooled-lo. That optimizer will assume the pool of IDs it can use is between <sequence value> and <sequence value>+<increment size>-1... which removes the problem mentioned above: if you restart your sequence to 3, Hibernate ORM will use IDs 3 to 52, which is exactly what you'd naively assume.

Interestingly, switching from the pooled optimizer to the pooled-lo optimizer... is a backwards-compatible change! If the pooled optimizer leaves the sequence with e.g. value 151 (intending to use values 101 to 151 in the next pool), then upon restarting after changing the optimizer, the pooled-lo optimizer will simply skip those values and use values 151 to 200 instead.

So, we could consider making the pooled-lo optimizer the default in Quarkus. The only problem would be if other actors hit the database and expect the pooled optimizer to be used; they might end up using IDs that the pooled-lo optimizer already used. We might consider this acceptable, since:

  1. Those collisions will lead to immediate error messages, assuming the DB has integrity constraints on primary keys (all DBs do, right? right?)
  2. People in this situation are probably advanced users who can debug this.

See https://docs.jboss.org/hibernate/orm/current/userguide/html_single/Hibernate_User_Guide.html#identifiers-generators-optimizer for documentation about Hibernate ORM optimizers.

Implementation ideas

No response

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    Status

    Done

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions