使用H2,
Environment.HBM2DDL_AUTO, "create"
如果数据库尚不存在,则创建数据库。
但是,在Postgres中,不会创建不存在的数据库,因此会引发异常,例如“ DB不存在”。有没有一种方法可以配置Postgres按需创建不存在的数据库?
以下配置文件可用于重现该问题:
使用H2可以正常工作:
package test.postgressql; import java.util.Properties; import javax.sql.DataSource; import org.hibernate.cfg.Environment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate4.HibernateExceptionTranslator; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @PropertySource("file:C:/springconfig/qpmlib.properties") @ComponentScan(basePackages = {"test.postgressql"}) @EnableJpaRepositories(basePackages = { "test.postgressql" }) @EnableTransactionManagement public abstract class H2DBConfig { @Autowired org.springframework.core.env.Environment env; public static final String DB_NAME = getNewDBName(); @Bean public DataSource dataSource() { DriverManagerDataSource dmds = new DriverManagerDataSource(); dmds.setDriverClassName("org.h2.Driver"); dmds.setUrl("jdbc:h2:tcp://localhost/~/" + DB_NAME ); dmds.setUsername(env.getProperty("h2user")); dmds.setPassword(env.getProperty("h2pw")); return dmds; } private static String getNewDBName() { return "H2DBTest"; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setDataSource(dataSource()); factory.setPersistenceUnitName(DB_NAME); factory.setPackagesToScan("test.postgressql"); factory.setJpaVendorAdapter(jpaAdapter()); factory.setJpaProperties(jpaProperties()); factory.afterPropertiesSet(); return factory; } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txm = new JpaTransactionManager( entityManagerFactory().getObject()); return txm; } @Bean public JpaVendorAdapter jpaAdapter() { HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setDatabase(Database.H2); adapter.setGenerateDdl(true); adapter.setShowSql(true); return adapter; } @Bean public HibernateExceptionTranslator exceptionTranslator() { return new HibernateExceptionTranslator(); } public Properties jpaProperties() { Properties properties = new Properties(); properties.put(Environment.SHOW_SQL, "true"); properties.put(Environment.HBM2DDL_AUTO, "create"); properties.put(Environment.DIALECT,"org.hibernate.dialect.H2Dialect"); return properties; } }
使用Postgres失败
package test.postgressql; import java.util.Properties; import javax.sql.DataSource; import org.hibernate.cfg.Environment; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.ComponentScan; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.PropertySource; import org.springframework.data.jpa.repository.config.EnableJpaRepositories; import org.springframework.jdbc.datasource.DriverManagerDataSource; import org.springframework.orm.hibernate4.HibernateExceptionTranslator; import org.springframework.orm.jpa.JpaTransactionManager; import org.springframework.orm.jpa.JpaVendorAdapter; import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean; import org.springframework.orm.jpa.vendor.Database; import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter; import org.springframework.transaction.PlatformTransactionManager; import org.springframework.transaction.annotation.EnableTransactionManagement; @Configuration @PropertySource("file:C:/springconfig/qpmlib.properties") @ComponentScan(basePackages = {"test.postgressql"}) @EnableJpaRepositories(basePackages = { "test.postgressql" }) @EnableTransactionManagement public abstract class PGDBConfig { @Autowired org.springframework.core.env.Environment env; public static final String DB_NAME = getNewDBName(); @Bean public DataSource dataSource() { DriverManagerDataSource dmds = new DriverManagerDataSource(); dmds.setDriverClassName("org.postgresql.Driver"); dmds.setUrl("jdbc:postgresql://localhost:5432/" + DB_NAME); dmds.setUsername(env.getProperty("postgresuser")); dmds.setPassword(env.getProperty("postgrespw")); return dmds; } private static String getNewDBName() { return "PostgresDBTest"; } @Bean public LocalContainerEntityManagerFactoryBean entityManagerFactory() { LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean(); factory.setDataSource(dataSource()); factory.setPersistenceUnitName(DB_NAME); factory.setPackagesToScan("test.postgressql"); factory.setJpaVendorAdapter(jpaAdapter()); factory.setJpaProperties(jpaProperties()); factory.afterPropertiesSet(); return factory; } @Bean public PlatformTransactionManager transactionManager() { JpaTransactionManager txm = new JpaTransactionManager( entityManagerFactory().getObject()); return txm; } @Bean public JpaVendorAdapter jpaAdapter() { HibernateJpaVendorAdapter adapter = new HibernateJpaVendorAdapter(); adapter.setDatabase(Database.POSTGRESQL); adapter.setGenerateDdl(true); adapter.setShowSql(true); return adapter; } @Bean public HibernateExceptionTranslator exceptionTranslator() { return new HibernateExceptionTranslator(); } public Properties jpaProperties() { Properties properties = new Properties(); properties.put(Environment.SHOW_SQL, "true"); properties.put(Environment.HBM2DDL_AUTO, "create"); properties.put(Environment.DIALECT,"org.hibernate.dialect.PostgreSQL9Dialect"); return properties; } }
该hbmddl工具只能为现有架构创建表,而不能为您创建架构。在运行该工具之前,数据库必须存在。这是因为数据库必须由管理员创建,并且应该为其分配所有者。
hbmddl
因为在大多数应用程序中,该应用程序只能访问具有限制性特权的数据库角色,所以不需要这种功能。
PostgreSQL不支持通过连接URL即时创建数据库。您可以InitializingBean使用管理帐户和默认的PostgreSQL数据库在应用程序启动时添加一个连接到数据库服务器的应用程序,如果应用程序数据库不存在,则可以发出CREATE DATABASE。或者,只需使用Flyway。
InitializingBean