How to get the All table metadata in spring boot - JPA - hibernate?

In Spring Boot, spring.jpa.properties points to a Map<String, String>, so it can only contain String values.

However in Hibernate, when the EntityManagerFactoryBuilderImpl reads hibernate.integrator_provider it expects to find an instance of IntegratorProvider and not a Class name, hence the exception.

You can however add a bean that implements HibernatePropertiesCustomizer to add the IntegrationProvider instance to the Hibernate properties:

@Component
public class HibernateConfig implements HibernatePropertiesCustomizer {

    @Override
    public void customize(Map<String, Object> hibernateProperties) {
        hibernateProperties.put("hibernate.integrator_provider",
                (IntegratorProvider) () -> Collections.singletonList(MetadataExtractorIntegrator.INSTANCE));
    }
}

I have created a working example in this repository.

If you are using Springboot 1.5.x, The "HibernatePropertiesCustomizer" is not exist.

I found a solution usable from here. You can not use integrator here, but you can add all the event listeners one by one. below is my code code:

public class RootAwareInsertEventListener implements PersistEventListener {

    public static final RootAwareInsertEventListener INSTANCE = new RootAwareInsertEventListener();

    @Override
    public void onPersist(PersistEvent event) throws HibernateException {
        final Object entity = event.getObject();

        if (entity instanceof RootAware) {
            RootAware rootAware = (RootAware) entity;
            Object root = rootAware.getRoot();
            event.getSession().lock(root, LockMode.OPTIMISTIC_FORCE_INCREMENT);

            log.info("Incrementing {} entity version because a {} child entity has been inserted",
                    root, entity);
        }
    }

    @Override
    public void onPersist(PersistEvent event, Map createdAlready)
            throws HibernateException {
        onPersist(event);
    }
}
@Component
public class HibernateListenerConfigurer {

    @PersistenceUnit
    private EntityManagerFactory emf;

    @PostConstruct
    protected void init() {
        SessionFactoryImpl sessionFactory = emf.unwrap(SessionFactoryImpl.class);
        EventListenerRegistry registry = sessionFactory.getServiceRegistry().getService(EventListenerRegistry.class);
        registry.getEventListenerGroup(EventType.PERSIST).appendListener(RootAwareInsertEventListener.INSTANCE);
        registry.getEventListenerGroup(EventType.FLUSH_ENTITY).appendListener(RootAwareUpdateAndDeleteEventListener.INSTANCE);

    }
}

In org.springframework.orm.hibernate5.LocalSessionFactoryBean, there is a variable argument setter method for hibernateIntegrators which will accept one or more instances of org.hibernate.integrator.spi.Integrator

So in org.springframework.orm.hibernate5.LocalSessionFactoryBean configuration add the below property

<property name="hibernateIntegrators" ref="metadataExtractorIntegrator" />

and make the Integrator as managed bean

    package com.test.ttv;
    import org.hibernate.boot.Metadata;
    import org.hibernate.boot.model.relational.Database;
    import org.hibernate.engine.spi.SessionFactoryImplementor;
    import org.hibernate.service.spi.SessionFactoryServiceRegistry;
    import org.springframework.stereotype.Component;

    @Component  
    public class MetadataExtractorIntegrator implements org.hibernate.integrator.spi.Integrator {

        private Database database;

        private Metadata metadata;

        public Database getDatabase() {
            return database;
        }

        public Metadata getMetadata() {
            return metadata;
        }

        @Override
        public void integrate(
                Metadata metadata,
                SessionFactoryImplementor sessionFactory,
                SessionFactoryServiceRegistry serviceRegistry) {

            this.database = metadata.getDatabase();
            this.metadata = metadata;

        }

        @Override
        public void disintegrate(
            SessionFactoryImplementor sessionFactory,
            SessionFactoryServiceRegistry serviceRegistry) {

        }
    }