localsessionfactorybean annotationsessionfactorybean java jpa configuration hbm2ddl hibernate-5.x

java - annotationsessionfactorybean - ¿Dónde entró Configuration.generateSchemaCreationScript() en Hibernate 5?



spring boot hibernate 5 configuration (4)

En caso de que uno esté usando JPA 2.1+, existe una posibilidad de compilación muy simple para generar el ddl. simplemente configure las siguientes propiedades jpa y se crearán los archivos ddl. Con el arranque de primavera uno podría escribir una clase principal separada con esas opciones de configuración específicas.

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 con JPA 2.1+

schemagenerator.properties (poner en la carpeta de recursos):

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(); } }

En Hibernate 4.x, solía generar y exportar el esquema como se define en las entidades anotadas de la siguiente manera (usando Spring para buscar entidades anotadas en la ruta de la clase):

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

Esto ya no funciona en Hibernate 5.0:

Realmente no encontré referencias obvias a este cambio en la guía de migración aparte de:

Se han eliminado bastantes métodos de la Configuración

¿Cuál es la forma correcta de generar y exportar una base de datos en una conexión JDBC existente con Hibernate 5.0 basada en un conjunto de entidades anotadas? (Las soluciones basadas en JPA puro también están bien)

(nota, simplemente eliminar la llamada a generateSchemaCreationScript() parece funcionar, pero preferiría asegurarme de hacerlo bien)


Gracias a las respuestas de Vlad y Gunnar , he logrado abrirme camino a través de la nueva API de configuración para producir la lógica de exportación equivalente con lo siguiente. Por supuesto, la historia muestra que esta API se romperá de nuevo, así que asegúrese de elegir la versión adecuada:

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 (sin advertencias):

Lo anterior producirá algunas advertencias desagradables, que pueden ser ignoradas:

Okt 20, 2016 2:57:16 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
ADVERTENCIA: HHH000181: No se encontró un proveedor de conexión apropiado, suponiendo que la aplicación proporcionará conexiones
Okt 20, 2016 2:57:16 PM org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
ADVERTENCIA: HHH000342: No se pudo obtener la conexión para consultar los metadatos: la aplicación debe proporcionar conexiones JDBC

... o trabajas a su alrededor pirateando el siguiente ConnectionProvider en la configuración (no debería ser necesario en mi opinión)

.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:

Como recordatorio, así es como funcionó esto en 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);


La nueva API de arranque permite muchas personalizaciones, pero suponiendo que no las necesita, la invocación más corta se vería así, aplicando valores predeterminados para los registros de servicio y todas las configuraciones:

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

Actualización: Proporcionando un ejemplo para aplicar propiedades de configuración

Hay varias maneras de insertar propiedades para la conexión URL, dialecto, etc. Por ejemplo, podría proporcionar un archivo hibernate.properties o utilizar un registro de servicio personalizado con la configuración requerida:

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


Un ejemplo de la nueva inicialización de SchemaExport se encuentra en 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 );

Por supuesto, puede personalizarlo según sus necesidades.