Spring-Boot 执行数据.sql仅在一个配置文件中

2022-09-02 01:46:59

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

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

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

我尝试过的事情:

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

  2. 已创建一个 .问题是当我使用它时,它不会自动创建数据库,而只应用指定的脚本。找不到自动创建数据库的方法。(这里这里EmbeddedDatabaseBuilderspring.jpa.hibernate.ddl-auto=create-drop)

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

一定有更简单的方法来说“嘿,春天......当我的配置文件是 时,在 strartup 上运行此脚本,对吗?data-devEmbeddedCreate.sqldevEmbeddedCreate


答案 1

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

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

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

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


答案 2

对于未来的读者。

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

以下是最重要的部分是:

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

这将加载未命名为“数据.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;
    }
}

推荐