Where did Configuration.generateSchemaCreationScript() go in Hibernate 5

后端 未结 5 1721
一向
一向 2020-12-01 07:23

In Hibernate 4.x, I used to generate and export the schema as defined in annotated entities as follows (using Spring to find annotated entities on the class path):



        
相关标签:
5条回答
  • 2020-12-01 08:05

    I exported it this way with 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);
        }
    }
    
    0 讨论(0)
  • 2020-12-01 08:16

    The new bootstrap API allows for many customizations, but assuming you don't need those, the shortest invocation would look like that, applying default values for service registries and all the settings:

    Metadata metadata = new MetadataSources()
        .addAnnotatedClass( MyEntity.class )
        .build();
    
    new SchemaExport( (MetadataImplementor) metadata )
        .setOutputFile( "my-statements.ddl" )
        .create( Target.NONE );
    

    Update: Providing example for applying configuration propperties

    There are several ways to inject properties for connection URL, dialect etc. E.g. you could provide a file hibernate.properties or you use a service registry customized with the required settings:

    StandardServiceRegistry registry = new StandardServiceRegistryBuilder()
        .applySetting( "hibernate.connection.url", "jdbc:h2:mem:db1;DB_CLOSE_DELAY=-1" )
        .build();
    
    Metadata metadata = new MetadataSources( registry )
        .build();
    
    0 讨论(0)
  • 2020-12-01 08:19

    Thanks to the answers by Vlad and Gunnar, I've managed to find my way through the new configuration API to produce the equivalent export logic with the following. Of course, history shows that this API will break again, so make sure to choose the appropriate version:

    Hibernate 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 (without warnings):

    The above will produce some nasty warnings, which can either be ignored:

    Okt 20, 2016 2:57:16 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
    WARN: HHH000181: No appropriate connection provider encountered, assuming application will be supplying connections
    Okt 20, 2016 2:57:16 PM org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
    WARN: HHH000342: Could not obtain connection to query metadata : The application must supply JDBC connections

    ... or you work around them by hacking the following ConnectionProvider into the settings (it shouldn't be required in my opinion)

            .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);
    

    Hibernate 4:

    As a reminder, here's how this worked in 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);
    
    0 讨论(0)
  • 2020-12-01 08:21

    In case one is using JPA 2.1+ - there is a very simple build-in possibility to generate the ddl. just set the following jpa properties and the ddl files will be created. With spring boot one could write a separate main class with those specific config options.

    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 Boot with JPA 2.1+

    schemagenerator.properties (put in resources folder):

    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();
        }
    }
    
    0 讨论(0)
  • 2020-12-01 08:29

    One example of the new SchemaExport initialization is found in 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 );
    

    Of course, you can customize it according to your needs.

    0 讨论(0)
提交回复
热议问题