Hybrid ID generation in Hibernate 6.2 is difficult

In Hibernate 6.2, it seems my ID generator can no longer work.

My generator uses an identity column/post-insert-id by default, but will use an explicitly supplied ID if entity.getExplicitId() returns non-null. This is handy when data is in the process of being migrated and the service can both insert new IDs as well as consume inserts (using supplied IDs) from another source.

The problem is that in 6.2, the way to choose between generation before execution (supplied ID) and generation after execution (post-insert) is via org.hibernate.generator.Generator.generatedOnExecution(). This method does not take the entity object as an argument, so the generator cannot decide at runtime which strategy to use. Is there another way to do it?

For reference, here is my generator implementation which was working in previous Hibernate versions:

public class ExplicitOrAutoGenerator extends IdentityGenerator {
    @Override
    public Serializable generate(SharedSessionContractImplementor s, Object obj) {
        if (obj instanceof ExplicitId entity && entity.getExplicitId() != null) {
            return entity.getExplicitId();
        }

        return IdentifierGeneratorHelper.POST_INSERT_INDICATOR;
    }
}

If I use it as-is (by implementing the new IdentifierGenerator interface), an insert with a post-insert ID just fails because it tries to call the entity ID setter with POST_INSERT_INDICATOR (which is not a Long or Integer obviously).

You can create a JIRA issue for this. Shouldn’t be too hard to fix this.

It affects me too.I created an account just to write this comment.

Did you create jira request? Could you attach link here?

I am affected as well, usecase:
When an entitiys id is present → use it when storing the entity.
If not: fall back to the databases auto_increment

I did it like this in the past (hibernate 6.1):

public class CustomIdentityGenerator extends IdentityGenerator {
    @Override
    public Object generate(SharedSessionContractImplementor sharedSessionContractImplementor, Object o) throws HibernateException {
        if (o instanceof TariffEntity) {
            TariffEntity t = (TariffEntity) o;
            if (t.getTariffId() != null && t.getTariffId() > 0) {
                return t.getTariffId();
            }
        }
        return super.generate(sharedSessionContractImplementor, o);
    }
}

Is there an alternate solution I could try? I tried implementing IdentifierGenerator, but that got me nowhere since indicating the fallback to the database is the problem (like above using IdentifierGeneratorHelper.POST_INSERT_INDICATOR)

This happened after upgrading Spring Boot 3.0 to 3.1, which translates to hibernate 6.1.7 to 6.2.2. The guide at 6.2 Migration Guide doesnt mention it, at least it is not obvious to me.

See [HHH-16692] - Hibernate JIRA

Ah ok, so a jira was indeed created, but untouched since may.

Also, please note that I am NOT using “IdentifierGeneratorHelper.POST_INSERT_INDICATOR”, but calling super to invoke the database default id behavior.

If anyone else comes upon this issue like I did:
For me(!!!) it is enough to force spring boot 3.1 to use the old hibernate version that was shipped with spring boot 3.0 by using the follwing property in the projects pom:

<properties>
   <hibernate.version>6.1.7.Final</hibernate.version>
</properties>

This is not a fix!
This is barely a workaround!
Just because it works for me, does not mean it works for any other usecase.