【问题标题】:Spring-Boot execute data.sql in one profile onlySpring-Boot 仅在一个配置文件中执行 data.sql
【发布时间】:2014-07-10 12:59:57
【问题描述】:

我有这个应用程序,它使用“默认”配置文件连接到 PostgreSQL 数据库并使用 Flyway 进行迁移。

我想创建另一个名为“devEmbeddedCreate”的配置文件,我需要在其中使用嵌入式数据库服务器 (h2),在 application.properties 文件中使用 spring.jpa.hibernate.ddl-auto=create-drop 创建数据库并执行一个名为“data.sql”的不同脚本初始化一些表。

如果我使用“data.sql”文件名保留脚本,则每次应用程序启动时都会执行它。这是我不想发生的事情,我需要它只在某个配置文件中执行。

我尝试过的事情:

  1. 文档中提到可以有一个schema-${platform}.sql 文件,您可以在配置中使用spring.datasource.platform 定义平台。它不适用于data-${platform}.sql 文件的问题。 (here)

  2. 创建了一个EmbeddedDatabaseBuilder。问题是当我使用它时,它不会自动创建数据库并且只应用指定的脚本。找不到像spring.jpa.hibernate.ddl-auto=create-drop 那样自动创建数据库的方法。 (herehere

  3. 寻找一种将 XML 配置转换为基于 Java 的配置的方法,找到了一种创建数据库的方法。经过大量调整和更改以在内存中工作后,它看起来很有希望,但无法找出数据库在启动时关闭(并删除其所有结构)的原因(here

    李>

必须有一种更简单的方式来说“嘿,春天……当我的个人资料是 devEmbeddedCreate 时,在启动这个 data-devEmbeddedCreate.sql 脚本上运行,对吧?

【问题讨论】:

    标签: java spring hibernate jpa spring-boot


    【解决方案1】:

    为未来的读者。

    我用一种稍微不同的方式解决了这个问题……使用“java config”。

    下面最重要的部分是:

    @豆 @Profile(SPRING_PROFILE_DEFAULT) public DataSourceInitializer getDataSourceInitializer(final DataSource dataSource) {

    这将加载未命名为“data.sql”的 .sql 文件....仅当该配置文件处于活动状态时。

    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.boot.jdbc.DataSourceBuilder;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.Profile;
    import org.springframework.core.env.Environment;
    import org.springframework.core.io.Resource;
    import org.springframework.dao.annotation.PersistenceExceptionTranslationPostProcessor;
    import org.springframework.jdbc.datasource.init.DataSourceInitializer;
    import org.springframework.jdbc.datasource.init.DatabasePopulator;
    import org.springframework.jdbc.datasource.init.ResourceDatabasePopulator;
    import org.springframework.orm.jpa.JpaTransactionManager;
    import org.springframework.orm.jpa.JpaVendorAdapter;
    import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
    import org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter;
    import org.springframework.transaction.PlatformTransactionManager;
    import org.springframework.transaction.annotation.EnableTransactionManagement;
    
    import javax.sql.DataSource;
    import java.util.Optional;
    import java.util.Properties;
    
    @Configuration
    @EnableTransactionManagement
    /* below @CS is not needed with setPackagesToScan */
    //@ComponentScan(basePackageClasses = {SomeJpaEntityOne.class, SomeJpaEntityTwo.class})
    public class PersistenceJpaConfig {
    
        public static final String SPRING_PROFILE_DEFAULT = "default";
    
        /* the below file-name is purposely not "data.sql" (or data-spring.sql) to avoid/bypass "auto-find" spring-data logic.  the file/resource is referred to later in a specific spring profile */
        @Value("classpath:developer.local.seed.data.dml.sql")
        private Resource seedDataLocalDeveloperResource;
    
        /**
         * @param env
         * @return
         */
        /* bean must be named entityManagerFactory to satisfy spring-jpa magic */
        @Bean(name = "entityManagerFactory")
        public LocalContainerEntityManagerFactoryBean entityManagerFactory(Environment env) {
            final LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean();
            em.setDataSource(this.getDataSourceOne());
    
            final String entityManagerFactoryPackagesToScanCsv = "com.myentitiespackageone,com.myentitiespackagetwo";
            String[] packagesArray = entityManagerFactoryPackagesToScanCsv.split(",");
            em.setPackagesToScan(packagesArray);
    
            final JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter();
            em.setJpaVendorAdapter(vendorAdapter);
            em.setJpaProperties(getCustomHibernateProperties(env, configMapRetriever));
    
            return em;
        }
    
        @Bean
        public DataSource getDataSourceOne() {
    
            DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create();
            dataSourceBuilder.driverClassName("myDataSourceDriverClassName");
            dataSourceBuilder.url("mydataSourceUrl");
            dataSourceBuilder.username("mydataSourceUserName");
            dataSourceBuilder.password("myPassword");
    
            DataSource returnItem = dataSourceBuilder.build();
            return returnItem;
        }
    
        /**
         * @param env
         * @param secretRetriever
         * @param configMapRetriever
         * @return JPA PlatformTransactionManager
         */
        /* This bean must be named 'transactionManager' to satisfy jpa string-magic */
        @Bean(name = "transactionManager")
        public PlatformTransactionManager getAPlatformTransactionManager(Environment env) {
            final JpaTransactionManager transactionManager = new JpaTransactionManager();
            transactionManager.setEntityManagerFactory(entityManagerFactory(env).getObject());
            return transactionManager;
        }
    
        /**
         * @return JPA PersistenceExceptionTranslationPostProcessor
         */
        @Bean
        public PersistenceExceptionTranslationPostProcessor getAPersistenceExceptionTranslationPostProcessor() {
            return new PersistenceExceptionTranslationPostProcessor();
        }
    
        final Properties getCustomHibernateProperties(Environment env, IConfigMapRetriever configMapRetriever) {
    
            Properties hibernateProperties = new Properties();
            /* not shown */
            /* but stuff like
    
                    "hibernate.dialect"
                    "hibernate.hbm2ddl.auto"
                    "hibernate.jdbc.batch_size"
                    "hibernate.jdbc.fetch_size"
                    "hibernate.order_inserts"
                    "hibernate.order_updates"
                    "hibernate.jdbc.batch_versioned_data"
                    "hibernate.generate_statistics"
                    "hibernate.show_sql"
                    "hibernate.format_sql"
    
            */
    
            return hibernateProperties;
        }
    
        /**
         * @param dataSource
         * @return
         */
        @Bean
        @Profile(SPRING_PROFILE_DEFAULT)
        public DataSourceInitializer getDataSourceInitializer(final DataSource dataSource) {
            final DataSourceInitializer initializer = new DataSourceInitializer();
            initializer.setDataSource(dataSource);
            initializer.setDatabasePopulator(getDatabasePopulator());
            return initializer;
        }
    
        private DatabasePopulator getDatabasePopulator() {
            final ResourceDatabasePopulator populator = new ResourceDatabasePopulator();
            populator.addScript(seedDataLocalDeveloperResource);
            return populator;
        }
    }
    

    【讨论】:

      【解决方案2】:

      您的方法 1) 走在了正确的轨道上,但您应该通过spring.datasource.platform 设置数据源平台,而不是spring.jpa.database-platform。脚本执行功能不是 JPA 特定的。

      您还可以通过设置spring.datasource.schema 属性手动指定要执行的SQL 脚本文件。这是org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration file in 1.0.2.RELEASE的摘录:

      String schema = this.datasourceProperties.getProperty("schema");
      if (schema == null) {
          schema = "classpath*:schema-"
                  + this.datasourceProperties.getProperty("platform", "all")
                  + ".sql,classpath*:schema.sql,classpath*:data.sql";
      }
      

      如您所见,文档中指定的文件集仅在您未指定自己的列表时使用。

      【讨论】:

      • 解决了我的问题,事实上我尝试使用spring.datasource.platform
      • 我错过的是使用schema-${platform}.sql 文件名并不能阻止spring.jpa.hibernate.ddl-auto=create-drop 正常工作。现在,我不太明白schema.sqldata.sql 之间的区别
      • 它正在工作。我的application.properties 包含spring.profiles.active=devEmbeddedCreate。我的application-devEmbeddedCreate.properties 文件包含:spring.jpa.database=POSTGRESQLspring.jpa.hibernate.ddl-auto=create-dropspring.datasource.platform=devEmbeddedCreate。我的脚本文件名是:schema-devEmbeddedCreate.sql。数据库创建得很好,脚本执行得很好。不需要其他任何东西。坦克你!
      • 定义spring.datasource.schema=classpath*:data-devEmbeddedCreate.sql,而不是spring.datasource.platform=devEmbeddedCreate,现在自动创建数据库并且脚本data-devEmbeddedCreate.sql工作正常
      • 我尝试了这种方法,我面临的问题是即使我设置了spring.datasource.initialization-mode=always spring.jpa.hibernate.ddl-auto=create-drop,但当我设置平台时,我的表并没有自动创建。有什么建议吗?
      猜你喜欢
      • 2021-10-06
      • 1970-01-01
      • 2020-08-05
      • 2016-04-03
      • 2016-07-03
      • 1970-01-01
      • 2018-12-31
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多