我想知道在应用程序启动之前加载初始数据库数据的最佳方法是什么?我要找的是一些东西,将填补我的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"));
}
}
但我非常怀疑这是不是最好的办法。真的是这样吗?
您可以创建一个数据。在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
最紧凑的(对于动态数据)将@mathias-dpunkt解决方案放入MainApp(使用Lombok @AllArgsConstructor):
@SpringBootApplication
@AllArgsConstructor
public class RestaurantVotingApplication implements ApplicationRunner {
private final VoteRepository voteRepository;
private final UserRepository userRepository;
public static void main(String[] args) {
SpringApplication.run(RestaurantVotingApplication.class, args);
}
@Override
public void run(ApplicationArguments args) {
voteRepository.save(new Vote(userRepository.getOne(1), LocalDate.now(), LocalTime.now()));
}
}
我创建了一个库,用于在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包。
如果您来到这里,似乎什么都不适合您,那么您可能受到了Spring Boot 2.5及以后引入的一些更改的影响。
这里是我为postgresql使用的全部属性集。
spring:
sql.init.mode: always <-----------------
datasource:
url: jdbc:postgresql://localhost:5432/products
username:
password:
jpa:
defer-datasource-initialization: true <------------------
hibernate:
ddl-auto: create-drop <----------------
database-platform: org.hibernate.dialect.PostgreSQLDialect
我还用<——标记了当前主题的相关属性,以便实现以下功能。
ORM供应商将从Java实体模型为您创建数据库模式。
创建数据库模式后,初始数据将从data.sql文件加载到数据库中
Ps:不要忘记添加文件的初始数据,数据。src/main/resources下的SQL
同样作为参考:Spring Boot 2.5发行说明