Рубрики
Без рубрики

Как получить сопоставление сущности с метаданными привязки таблицы базы данных из спящего режима

Автор оригинала: Vlad Mihalcea.

Вступление

Лукас Эдер опубликовал очень интересный вопрос о StackOverflow , спрашивающий о способе получения доступа к метаданным привязки между сопоставлениями сущностей и таблицами базы данных.

Хотя я ранее отвечал на аналогичный вопрос , используя эту статью, я понял, что конкретный вариант использования был намного проще, поскольку он извлекал только метаданные базы данных. В этой статье вы увидите, как легко вы можете получить информацию о мосте между вашими сущностями JPA и базовой схемой базы данных.

Как получить сопоставление сущности с метаданными привязки таблицы базы данных из Hibernate @vlad_mihalcea https://t.co/w972BC1ty0 pic.twitter.com/QXrrnYdOuK

Интегратор

Hibernate очень гибкий, поэтому он определяет множество SPI (интерфейсов поставщика услуг), которые вы можете зарегистрировать для настройки внутренних компонентов Hibernate. Одним из таких интерфейсов является org.hibernate.integrator.spi.Integrator , который используется многими технологиями, интегрируемыми с Hibernate ORM, такими как проверка компонентов, Envers или поставщик безопасности JACC.

Используя API Hibernate Integrator, мы можем написать наш собственный компонент, который фиксирует метаданные SessionFactory во время сборки, которые в противном случае доступны только во время начальной загрузки.

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

    public static final MetadataExtractorIntegrator INSTANCE = 
        new MetadataExtractorIntegrator();

    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) {

    }
}

Файл org.hibernate.boot.Метаданные – это то, что нас интересует, поскольку они содержат привязки постоянных классов сущностей.

Для регистрации Интегратора извлечения метаданных с помощью Hibernate у нас есть две возможности, основанные на базовом методе начальной загрузки.

Спящий режим-собственная начальная загрузка

Если вы используете встроенную загрузочную программу Hibernate, вы можете зарегистрировать Интегратор с помощью BootstrapServiceRegistryBuilder следующим образом:

final BootstrapServiceRegistry bootstrapServiceRegistry = 
    new BootstrapServiceRegistryBuilder()
    .enableAutoClose()
    .applyIntegrator( MetadataExtractorIntegrator.INSTANCE )
    .build();

final StandardServiceRegistry serviceRegistry = 
    new StandardServiceRegistryBuilder(bootstrapServiceRegistry)
    .applySettings(properties())
    .build();

Загрузчик JPA

Если вы используете загрузчик JPA, то вы можете зарегистрировать Интегратор с помощью BootstrapServiceRegistryBuilder следующим образом:

Map configuration = new HashMap<>();

Integrator integrator = integrator();
if (integrator != null) {
    configuration.put("hibernate.integrator_provider", 
        (IntegratorProvider) () -> Collections.singletonList(
            MetadataExtractorIntegrator.INSTANCE
        )
    );
}

EntityManagerFactory entityManagerFactory = new EntityManagerFactoryBuilderImpl(
    new PersistenceUnitInfoDescriptor(persistenceUnitInfo), 
    configuration
)
.build();

Это для тех случаев, когда вы хотите загрузить JPA без каких-либо persistence.xml файл конфигурации .

Чтобы узнать, как можно задать свойство конфигурации hibernate.integrator_provider при использовании Spring с JPA или Spring с Hibernate, ознакомьтесь с этой статьей .

Модель предметной области

Предполагая, что у нас есть следующие таблицы базы данных, сопоставленные нашим приложением JPA:

При выполнении следующего тестового случая:

Metadata metadata = MetadataExtractorIntegrator.INSTANCE.getMetadata();

for ( PersistentClass persistentClass : metadata.getEntityBindings()) {

    Table table = persistentClass.getTable();
    
    LOGGER.info( "Entity: {} is mapped to table: {}",
                 persistentClass.getClassName(),
                 table.getName()
    );

    for(Iterator propertyIterator = persistentClass.getPropertyIterator(); 
            propertyIterator.hasNext(); ) {
        Property property = (Property) propertyIterator.next();
        
        for(Iterator columnIterator = property.getColumnIterator(); 
                columnIterator.hasNext(); ) {
            Column column = (Column) columnIterator.next();
            
            LOGGER.info( "Property: {} is mapped on table column: {} of type: {}",
                         property.getName(),
                         column.getName(),
                         column.getSqlType()
            );
        }
    }
}

Режим гибернации генерирует следующие выходные данные:

Entity: com.vladmihalcea.book.hpjp.util.providers.entity.BlogEntityProvider$Tag is mapped to table: tag
Property: name is mapped on table column: name of type: varchar(255)
Property: version is mapped on table column: version of type: integer

Entity: com.vladmihalcea.book.hpjp.util.providers.entity.BlogEntityProvider$PostComment is mapped to table: post_comment
Property: post is mapped on table column: post_id of type: bigint
Property: review is mapped on table column: review of type: varchar(255)
Property: version is mapped on table column: version of type: integer

Entity: com.vladmihalcea.book.hpjp.util.providers.entity.BlogEntityProvider$Post is mapped to table: post
Property: title is mapped on table column: title of type: varchar(255)
Property: version is mapped on table column: version of type: integer

Entity: com.vladmihalcea.book.hpjp.util.providers.entity.BlogEntityProvider$PostDetails is mapped to table: post_details
Property: createdBy is mapped on table column: created_by of type: varchar(255)
Property: createdOn is mapped on table column: created_on of type: datetime(6)
Property: version is mapped on table column: version of type: integer

Вывод

Hibernate легко настраивается, и Интегратор SPI позволяет вам получить доступ к метаданным Hibernate , которые вы можете позже просмотреть в своем корпоративном приложении.