Автор оригинала: 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
следующим образом:
Mapconfiguration = 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
, которые вы можете позже просмотреть в своем корпоративном приложении.