hibernatejpaspring-dataentitymanagersessionfactory

How to register a custom Hibernate IdentifierGenerator with the JPA EntityManager?


When using plain Hibernate this can be done in the following way:

public class MyLocalSessionFactoryBean extends LocalSessionFactoryBean {

    // can also be made configurable e.g. with Springs EL...
    private Class myIdentifierGeneratorClass = MyIdentifierGeneratorClass.class;

    @Override
    protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder sfb) {

        Configuration config = getConfiguration();
        MutableIdentifierGeneratorFactory identifierGeneratorFactory = config.getIdentifierGeneratorFactory();
        identifierGeneratorFactory.register("xyz", myIdentifierGeneratorClass);

        return super.buildSessionFactory(sfb);
    }
}

Now it's possible to write e.g.

@MappedSuperclass
public class BaseEntity implements Serializable {

    @Id
    @GeneratedValue(generator = "generatorName")
    @GenericGenerator(name = "generatorName", strategy = "xyz")
    private Long id;
}

How can this be achieved when using Hibernate JPA EntityManager?

Maybe by utilising LocalContainerEntityManagerFactoryBean#postProcessEntityManagerFactory(EntityManagerFactory emf, PersistenceUnitInfo pui)?

I've also found EntityManagerFactoryBuilderImpl#buildHibernateConfiguration(ServiceRegistry serviceRegistry) but I don't know where to "hook in" (I'm using Spring and/or Spring-Boot and Spring-Data).

Thanks in advance!


Solution

  • You need to provide a hibernate.ejb.identifier_generator_strategy_provider configuration property which defines the fully qualified name of your IdentifierGeneratorStrategyProvider implementation.

    This IdentifierGeneratorStrategyProvider interface defines the following method:

    public Map<String,Class<?>> getStrategies();
    

    which you need to implement and define your own strategy there.

    During bootstrap the EntityManager will be configured like this:

    final Object idGeneratorStrategyProviderSetting = configurationValues.remove( AvailableSettings.IDENTIFIER_GENERATOR_STRATEGY_PROVIDER );
    if ( idGeneratorStrategyProviderSetting != null ) {
        final IdentifierGeneratorStrategyProvider idGeneratorStrategyProvider =
                strategySelector.resolveStrategy( IdentifierGeneratorStrategyProvider.class, idGeneratorStrategyProviderSetting );
        final MutableIdentifierGeneratorFactory identifierGeneratorFactory = ssr.getService( MutableIdentifierGeneratorFactory.class );
        if ( identifierGeneratorFactory == null ) {
            throw persistenceException(
                    "Application requested custom identifier generator strategies, " +
                            "but the MutableIdentifierGeneratorFactory could not be found"
            );
        }
        for ( Map.Entry<String,Class<?>> entry : idGeneratorStrategyProvider.getStrategies().entrySet() ) {
            identifierGeneratorFactory.register( entry.getKey(), entry.getValue() );
        }
    }
    

    so, the strategy you define will be configured in the MutableIdentifierGeneratorFactory just as you were doing previously.