Подтвердить что ты не робот

Где ConfigurationGenerateSchemaCreationScript() переместился в Hibernate 5

В Hibernate 4.x я использовал для генерации и экспорта схемы, как определено в аннотированных объектах, следующим образом (используя Spring для поиска аннотированных объектов в пути класса):

Connection connection = 
    DriverManager.getConnection("jdbc:h2:mem:jooq-meta-extensions", "sa", "");

Configuration configuration = new Configuration()
    .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");

// [...] adding annotated classes to Configuration here...

configuration.generateSchemaCreationScript(
    Dialect.getDialect(configuration.getProperties()));
SchemaExport export = new SchemaExport(configuration, connection);
export.create(true, true);

Это больше не работает в Hibernate 5.0:

Я действительно не нашел никаких очевидных ссылок на это изменение в руководстве по миграции, кроме:

Из конфигурации было удалено несколько методов

Каков правильный способ создания и экспорта базы данных на существующее соединение JDBC с Hibernate 5.0 на основе набора аннотированных объектов? (Чистые решения на основе JPA также прекрасны)

(обратите внимание, что просто удаление вызова generateSchemaCreationScript() похоже работает, но я бы предпочел убедиться, что это правильно)

4b9b3361

Ответ 1

Благодаря ответам Влад и Gunnar, мне удалось найти свой путь через новый API конфигурации для создания эквивалентной логики экспорта следующим образом. Конечно, история показывает, что этот API снова сломается, поэтому обязательно выберите подходящую версию:

Спящий режим 5.2:

MetadataSources metadata = new MetadataSources(
    new StandardServiceRegistryBuilder()
        .applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
        .applySetting("javax.persistence.schema-generation-connection", connection)
        .build());

// [...] adding annotated classes to metadata here...
metadata.addAnnotatedClass(...);

SchemaExport export = new SchemaExport();
export.create(EnumSet.of(TargetType.DATABASE), metadata.buildMetadata());

Hibernate 5.2 (без предупреждений):

Вышеупомянутые вызовы вызовут некоторые неприятные предупреждения, которые можно игнорировать:

Okt 20, 2016 2:57:16 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
WARN: HHH000181: Отсутствует соответствующий поставщик соединения, предполагая, что приложение будет поставлять соединения
 Okt 20, 2016 2:57:16 вечера org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
WARN: HHH000342: Не удалось получить соединение с метаданными запроса: приложение должно поставлять соединения JDBC

... или вы обходите их, взломав следующие ConnectionProvider в настройки (на мой взгляд, это не обязательно)

        .applySetting(AvailableSettings.CONNECTION_PROVIDER, new ConnectionProvider() {
            @Override
            public boolean isUnwrappableAs(Class unwrapType) {
                return false;
            }
            @Override
            public <T> T unwrap(Class<T> unwrapType) {
                return null;
            }
            @Override
            public Connection getConnection() {
                return connection; // Interesting part here
            }
            @Override
            public void closeConnection(Connection conn) throws SQLException {}

            @Override
            public boolean supportsAggressiveRelease() {
                return true;
            }
        })

Hibernate 5.0:

MetadataSources metadata = new MetadataSources(
    new StandardServiceRegistryBuilder()
        .applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
        .build());

// [...] adding annotated classes to metadata here...
metadata.addAnnotatedClass(...);

SchemaExport export = new SchemaExport(
    (MetadataImplementor) metadata.buildMetadata(),
    connection // pre-configured Connection here
);
export.create(true, true);

Спящий режим 4:

Напоминаем, как это работает в Hibernate 4:

Configuration configuration = new Configuration()
    .setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect");

// [...] adding annotated classes to metadata here...
configuration.addAnnotatedClass(...);

configuration.generateSchemaCreationScript(
    Dialect.getDialect(configuration.getProperties()));
SchemaExport export = new SchemaExport(configuration, connection);
export.create(true, true);

Ответ 2

Один пример новой инициализации SchemaExport находится в SchemaExportTask:

final BootstrapServiceRegistry bsr = new BootstrapServiceRegistryBuilder().build();

final MetadataSources metadataSources = new MetadataSources( bsr );
final StandardServiceRegistryBuilder ssrBuilder = new StandardServiceRegistryBuilder( bsr );

if ( configurationFile != null ) {
    ssrBuilder.configure( configurationFile );
}
if ( propertiesFile != null ) {
    ssrBuilder.loadProperties( propertiesFile );
}
ssrBuilder.applySettings( getProject().getProperties() );

for ( String fileName : getFiles() ) {
    if ( fileName.endsWith(".jar") ) {
        metadataSources.addJar( new File( fileName ) );
    }
    else {
        metadataSources.addFile( fileName );
    }
}


final StandardServiceRegistryImpl ssr = (StandardServiceRegistryImpl) ssrBuilder.build();
final MetadataBuilder metadataBuilder = metadataSources.getMetadataBuilder( ssr );

ClassLoaderService classLoaderService = bsr.getService( ClassLoaderService.class );
if ( implicitNamingStrategy != null ) {
    metadataBuilder.applyImplicitNamingStrategy(
            (ImplicitNamingStrategy) classLoaderService.classForName( implicitNamingStrategy ).newInstance()
    );
}
if ( physicalNamingStrategy != null ) {
    metadataBuilder.applyPhysicalNamingStrategy(
            (PhysicalNamingStrategy) classLoaderService.classForName( physicalNamingStrategy ).newInstance()
    );
}

return new SchemaExport( (MetadataImplementor) metadataBuilder.build() )
    .setHaltOnError( haltOnError )
    .setOutputFile( outputFile.getPath() )
    .setDelimiter( delimiter );

Конечно, вы можете настроить его в соответствии с вашими потребностями.

Ответ 3

Новый скрипт загрузки для многих настроек, но если вы не нуждаетесь в них, самый короткий вызов будет выглядеть так, применяя значения по умолчанию для сервисных реестров и всех настроек:

Metadata metadata = new MetadataSources()
    .addAnnotatedClass( MyEntity.class )
    .build();

new SchemaExport( (MetadataImplementor) metadata )
    .setOutputFile( "my-statements.ddl" )
    .create( Target.NONE );

Обновление: Предоставление примера для настройки конфигурации

Существует несколько способов ввода свойств URL-адреса подключения, диалекта и т.д. Например. вы можете предоставить файл hibernate.properties или использовать реестр служб, настроенный с требуемыми настройками:

StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
    .applySetting( "hibernate.connection.url", "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" )
    .build();

Metadata metadata = new MetadataSources( registry )
    .build();

Ответ 4

В случае использования JPA 2.1+ - существует очень простая встроенная возможность генерации ddl. просто установите следующие свойства jpa и создайте файлы ddl. При загрузке spring можно написать отдельный основной класс с этими конкретными параметрами конфигурации.

JPA 2.1 +

javax.persistence.schema-generation.scripts.action=drop-and-create
javax.persistence.schema-generation.scripts.create-target=create.ddl
javax.persistence.schema-generation.scripts.drop-target=drop.ddl

Spring Загрузка с JPA 2.1 +

schemagenerator.properties(поместить в папку ресурсов):

spring.jpa.properties.javax.persistence.schema-generation.scripts.action=drop-and-create
spring.jpa.properties.javax.persistence.schema-generation.scripts.create-target=create.ddl
spring.jpa.properties.javax.persistence.schema-generation.scripts.drop-target=drop.ddl
flyway.enabled=false // in case you use flyway for db maintenance

Spring Boot SchemaGenerator:

public class SchemaGenerator {
    public static void main(String[] args) throws Exception {
        SpringApplication.run(Application.class, new String[]{"--spring.config.name=schemagenerator"}).close();
    }
}