34

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 では機能しなくなりました。

移行ガイドには、次の点を除けば、この変更に関する明らかな参照は見つかりませんでした。

かなりの数のメソッドが構成から削除されました

注釈付きエンティティのセットに基づいて、Hibernate 5.0 を使用して既存の JDBC 接続でデータベースを生成およびエクスポートする正しい方法は何ですか? (純粋な JPA ベースのソリューションも問題ありません)

(注:への呼び出しを削除するだけでgenerateSchemaCreationScript()うまくいくようですが、これを正しく行うことをお勧めします)

4

5 に答える 5

32

VladGunnarによる回答のおかげで、新しい構成 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 initializeService
WARN: HHH000181: アプリケーションが接続を提供すると仮定すると、適切な接続プロバイダーが見つかりません
2016 年 10 月 20 日 2:57:16 PM org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator
initializeService 警告: 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;
            }
        })

休止状態 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);
于 2015-08-26T12:48:17.530 に答える
4

新しい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 );

もちろん、必要に応じてカスタマイズできます。

于 2015-08-24T08:57:10.003 に答える
3

新しいブートストラップ API では多くのカスタマイズが可能ですが、それらが必要ないと仮定すると、最短の呼び出しは次のようになり、サービス レジストリとすべての設定にデフォルト値が適用されます。

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();
于 2015-08-24T12:25:37.820 に答える
1

hibernate 5.4.9.Final でこのようにエクスポートしました。

import org.hibernate.boot.Metadata;
import org.hibernate.boot.MetadataSources;
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
import org.hibernate.tool.hbm2ddl.SchemaExport;
import org.hibernate.tool.schema.TargetType;

import java.util.EnumSet;

public class ExportSchema {
    public static void main(String[] args) {
        final StandardServiceRegistry serviceRegistry = new StandardServiceRegistryBuilder()
                .applySetting("hibernate.dialect", "org.hibernate.dialect.H2Dialect")
                .build();
        final Metadata metadata = new MetadataSources(serviceRegistry)
                .addAnnotatedClass(...)
                .buildMetadata();
        new SchemaExport()
                .setFormat(true)
                .setDelimiter(";")
                .setOutputFile("schema.sql")
                .execute(EnumSet.of(TargetType.SCRIPT), SchemaExport.Action.CREATE, metadata);
    }
}
于 2019-12-25T19:10:30.793 に答える
0

JPA 2.1+ を使用している場合、ddl を生成するための非常に単純な組み込み機能があります。次の jpa プロパティを設定するだけで、ddl ファイルが作成されます。スプリング ブートを使用すると、これらの特定の構成オプションを使用して別のメイン クラスを作成できます。

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

JPA 2.1+ を使用した Spring Boot

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();
    }
}
于 2016-06-09T11:45:32.513 に答える