我想知道在应用程序启动之前加载初始数据库数据的最佳方法是什么?我要找的是一些东西,将填补我的H2数据库与数据。

例如,我有一个域模型“User”,我可以通过访问/users访问用户,但最初在数据库中不会有任何用户,所以我必须创建它们。有没有办法自动用数据填充数据库?

目前,我有一个Bean,它由容器实例化并为我创建用户。

例子:

@Component
public class DataLoader {

    private UserRepository userRepository;

    @Autowired
    public DataLoader(UserRepository userRepository) {
        this.userRepository = userRepository;
        LoadUsers();
    }

    private void LoadUsers() {
        userRepository.save(new User("lala", "lala", "lala"));
    }
}

但我非常怀疑这是不是最好的办法。真的是这样吗?


当前回答

您可以向应用程序添加spring.datasource.data属性。列出要运行的SQL文件的属性。是这样的:

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql

//or (depending on SB version)

spring.sql.init.data-locations=classpath:accounts.sql, classpath:books.sql, file:reviews.sql

然后将运行每个文件中的sql insert语句,以便保持整洁。

如果你把文件放在类路径中,例如src/main/resources,它们就会被应用。或者将classpath:替换为file:,并使用文件的绝对路径

如果你想运行DDL类型的SQL,那么使用:

spring.datasource.schema=classpath:create_account_table.sql

// depending on spring version

spring.sql.init.schema-locations=classpath:create_account_table.sql 

编辑:这些解决方案可以让你快速启动和运行,但是对于更适合生产的解决方案,值得考虑一个框架,如flyway或libase。这些框架很好地与spring集成,并提供了一种快速、一致、版本控制的初始化模式和站立数据的方法。

其他回答

您可以向应用程序添加spring.datasource.data属性。列出要运行的SQL文件的属性。是这样的:

spring.datasource.data=classpath:accounts.sql, classpath:books.sql, classpath:reviews.sql

//or (depending on SB version)

spring.sql.init.data-locations=classpath:accounts.sql, classpath:books.sql, file:reviews.sql

然后将运行每个文件中的sql insert语句,以便保持整洁。

如果你把文件放在类路径中,例如src/main/resources,它们就会被应用。或者将classpath:替换为file:,并使用文件的绝对路径

如果你想运行DDL类型的SQL,那么使用:

spring.datasource.schema=classpath:create_account_table.sql

// depending on spring version

spring.sql.init.schema-locations=classpath:create_account_table.sql 

编辑:这些解决方案可以让你快速启动和运行,但是对于更适合生产的解决方案,值得考虑一个框架,如flyway或libase。这些框架很好地与spring集成,并提供了一种快速、一致、版本控制的初始化模式和站立数据的方法。

您可以创建一个数据。在src/main/resources文件夹中的SQL文件,它将在启动时自动执行。在这个文件中,你可以添加一些插入语句,例如:

INSERT INTO users (username, firstname, lastname) VALUES
  ('lala', 'lala', 'lala'),
  ('lolo', 'lolo', 'lolo');

类似地,您可以创建一个模式。SQL文件(或schema-h2. SQL)来创建你的模式:

CREATE TABLE task (
  id          INTEGER PRIMARY KEY,
  description VARCHAR(64) NOT NULL,
  completed   BIT NOT NULL);

虽然通常情况下你不需要这样做,因为Spring引导已经配置Hibernate来基于你的实体为内存数据库创建模式。如果你真的想使用模式。SQL,你必须禁用这个功能添加到你的application.properties:

spring.jpa.hibernate.ddl-auto=none

更多信息可以在关于数据库初始化的文档中找到。


如果使用Spring Boot 2,数据库初始化只适用于嵌入式数据库(H2, HSQLDB,…)。如果你想在其他数据库中使用它,你需要改变初始化模式属性:

spring.sql.init.mode=always # Spring Boot >=v2.5.0
spring.datasource.initialization-mode=always # Spring Boot <v2.5.0

如果使用多个数据库供应商,可以将文件命名为data-h2。SQL或data-mysql。SQL,这取决于您想使用的数据库平台。

要做到这一点,你必须配置数据源平台属性:

spring.sql.init.platform=h2 # Spring Boot >=v2.5.0
spring.datasource.platform=h2 # Spring Boot <v2.5.0

我创建了一个库,用于在Spring Boot应用程序中加载初始/演示数据。你可以在https://github.com/piotrpolak/spring-boot-data-fixtures上找到它

一旦数据fixture启动器位于类路径上,它将在应用程序启动时自动尝试加载DICTIONARY数据(此行为可以由属性控制)—您所需要做的就是注册一个实现DataFixture的bean。

我发现通过代码加载初始数据优于使用SQL脚本加载:

fixture的逻辑与应用程序逻辑/领域模型非常接近,随着领域的发展,它也会进行重构 你可以从增量的演示数据更新中获益——想象一个QA环境中有一些用户数据(在应用程序部署后不需要丢失),但同时你想为你开发的新功能添加数据

数据夹具示例:

/**
 * You can have as many fixture classes as you want.
 * @Order annotation is respected for the fixtures belonging to the same set.
 * You can make your demo database to be incrementally updated with fresh data
 * each time the application is redeployed - all you need to do is to write
 * a good condition in `canBeLoaded()` method.
 */
@Component
public class InitialDataFixture implements DataFixture {

    private final LanguageRepository languageRepository;

    // ...

    @Override
    public DataFixtureSet getSet() {
      return DataFixtureSet.DICTIONARY;
    }

    /**
     * We want to make sure the fixture is applied once and once only.
     * A more sophisticated condition can be used to create incremental demo data
     * over time without the need to reset the QA database (for example).
     */
    @Override
    public boolean canBeLoaded() {
      return languageRepository.size() == 0;
    }

    /**
     * The actual application of the fixture.
     * Assuming that data fixtures are registered as beans, this method can call
     * other services and/or repositories.
     */
    @Override
    public void load() {
      languageRepository.saveAll(Arrays.asList(
          new Language("en-US"), new Language("pl-PL")));
    }
}

这个概念的灵感来自Symfony Doctrine数据fixture包。

如果有人在努力使这个工作,即使是在接受的答案之后,对我来说,只在我的src/test/资源/应用程序中添加工作。yml H2数据源详细信息:

spring:
  datasource:
    platform: h2
    url: jdbc:h2:mem:test;DB_CLOSE_DELAY=-1
    driver-class-name: org.h2.Driver
    username: sa
    password:

您可以简单地创建一个导入。在src/main/resources中创建一个sql文件,Hibernate将在创建模式时执行它。