在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:
除了migration guide之外,我并没有真正找到任何对这种变化的明显引用:
已从配置
中删除了相当多的方法
基于一组带注释的实体,使用Hibernate 5.0在现有JDBC连接上生成和导出数据库的正确方法是什么? (基于JPA的纯解决方案也很好)
(请注意,只需删除对generateSchemaCreationScript()
的调用似乎有效,但我希望确保能够做到这一点)
答案 0 :(得分:27)
感谢Vlad和Gunnar的答案,我设法通过新配置API找到了解决方案,以生成具有以下内容的等效导出逻辑。当然,历史记录显示此API将再次中断,因此请务必选择合适的版本:
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());
上面会产生一些令人讨厌的警告,可以忽略:
Okt 20,2016 2:57:16 PM org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator initiateService
警告:HHH000181:假设应用程序将提供连接,则没有遇到任何适当的连接提供商 Okt 20,2016 2:57:16 PM org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator initiateService
警告: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;
}
})
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中的工作原理:
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);
答案 1 :(得分: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 );
当然,您可以根据自己的需要进行自定义。
答案 2 :(得分: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();
答案 3 :(得分:0)
如果一个人正在使用JPA 2.1+ - 生成ddl有一个非常简单的内置可能性。只需设置以下jpa属性,即可创建ddl文件。使用spring boot,可以使用这些特定的配置选项编写一个单独的主类。
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(放入资源文件夹):
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();
}
}
答案 4 :(得分:0)
我用休眠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);
}
}