SpringOrm — проблема миграции в режим гибернации с 4 по 5 — необходимо изменить метаданные перед созданием SessionFactory

#java #hibernate #sessionfactory #hibernate-5.x #spring-orm

#java #спящий режим #sessionfactory #спящий режим-5.x #весна-orm

Вопрос:

Я пытаюсь перейти с режима гибернации 4.3.11 на 5.4.x с помощью Spring-Orm 4.3.29. В рамках обновления мне нужно перенести существующую пользовательскую логику, которая зависит от NamedSQLQueries, полученных из класса конфигурации Hibernate. Эта пользовательская логика изменяет NamedSQLQueries и обновляется до исходной карты перед созданием SessionFactory. В новой версии (5.x) — я изменил начальную загрузку в соответствии с новой документацией и смог создать метаданные, но не смог изменить namedNativeQueries (метаданные документации неизменяемы). Есть ли способ изменить метаданные перед созданием SessionFactory.

Текущий код —

 public class CustomFactoryBean extends LocalSessionFactoryBean {
...

    @Override
    protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder localSessionFactoryBuilder) {
      localSessionFactoryBuilder.buildMappings(); //deprecated in 5.x
      mutateNamedSQLQueries(localSessionFactoryBuilder.getNamedSQLQueries()); //mutates NamedSQLQueries and updates back to the Map (Map<String, NamedSQLQueryDefinition>) AND localSessionFactoryBuilder.getNamedSQLQueries() returns nothing in 5.x (deprecated)
      localSessionFactoryBuilder.buildSessionFactory();
    }

}
 

Новый Код —

     @Override
    protected SessionFactory buildSessionFactory(LocalSessionFactoryBuilder localSessionFactoryBuilder) {

            final BootstrapServiceRegistry bootstrapServiceRegistry = new BootstrapServiceRegistryBuilder()
                    .enableAutoClose()
                    .applyIntegrator(MetadataExtractorIntegrator.INSTANCE) //MetadataExtractorIntegrator class is based on the 2nd link below
                    .build();
            
            final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder(bootstrapServiceRegistry)
                    .applySettings(localSessionFactoryBuilder.getProperties())
                    .build();
            
            MetadataSources metadataSources = new MetadataSources(serviceRegistry);
            metadataSources.addAnnotatedClass(TestEntity.class);
            
            Metadata metadata = metadataSources.buildMetadata();
            
            List<NamedSQLQueryDefinition> namedSQLQueryDefinitions = new ArrayList<>(metadata.getNamedNativeQueryDefinitions());
            mutateNamedNativeQueries(namedSQLQueryDefinitions); //not able to mutate namedSQLQueryDefinitions since metadata is immutable

            return metadata.buildSessionFactory();

    }

 

По этой ссылке — https://hibernate.atlassian.net/browse/HHH-12089 , похоже, что правильный способ изменить метаданные перед их созданием — использовать MetadataContributor, но я не вижу примера или какого-либо упоминания в официальной документации, где и как подключить пользовательский MetadataContributor.

Ссылки — Создание SessionFactory в Hibernate 5
https://docs.jboss.org/hibernate/stable/orm/userguide/html_single/Hibernate_User_Guide.html#bootstrap-native-SessionFactory

Для чтения метаданных после создания SessionFactory
https://vladmihalcea.com/how-to-get-access-to-database-table-metadata-with-hibernate-5 /

Любая помощь по этому вопросу будет высоко оценена.

Ответ №1:

В a MetadataContributor вы можете удалять записи InFlightMetadataCollector#getNamedQueryDefinitions и повторно добавлять их после внесения изменений.

Комментарии:

1. Я создал CustomContributor, как показано ниже, но я не вижу способа добавить участника в процесс начальной загрузки. общедоступный класс CustomMetadataContributor реализует MetadataContributor { @Override public void contribute(InFlightMetadataCollector metadataCollector, IndexView jandexIndex) { Коллекция<NamedSQLQueryDefinition> namedNativeQueryDefinitions = metadataCollector.getNamedNativeQueryDefinitions(); mutateNamedSQLQueries(namedNativeQueryDefinitions); } частная пустота mutateNamedSQLQueries(коллекция<NamedSQLQueryDefinition> namedNativeQueryDefinitions) { //мутировать здесь } }

2. Повторите именованный собственный запрос и удалите элемент, который вы хотите заменить. После этого вызовите метод addNamedNativeQuery

3. Я повторил и изменил требуемый элемент и добавил его обратно как новый элемент, используя addNamedNativeQuery, но эта логика не вызывается в процессе начальной загрузки. Нужно ли мне добавлять этот CustomContributor в StandardServiceRegistry или MetadataSources или что-то еще, чтобы эта логика вызывалась?

4. code — NamedSQLQueryDefinition namedNativeQueryDefinition = metadataCollector.getNamedNativeQueryDefinition(«TestEntity.namedNativeQuery»);namedNativeQueryDefinition.getQueryString().replace(«TEST» , «TEST_TEMP»);metadataCollector.addNamedNativeQuery(новый NamedSQLQueryDefinitionBuilder().setName(namedNativeQueryDefinition.getName()).setFetchSize(namedNativeQueryDefinition.getFetchSize()).createNamedQueryDefinition());

5. Привет, Крис, метод переопределения в пользовательском контрибьюторе вызывается после добавления имени класса пользовательского контрибьютора в файл org.hibernate.boot.spi.MetadataContributor в каталоге resources / META-INF / services, но проблема в том, что ни один из компонентов Spring не доступен в этом пользовательском контрибьюторе, что затрудняет мой процесс мутации. Я пропустил ввод участника в неправильном месте? Не могли бы вы предложить?