在这篇文章中,我们将看看用Spring Boot加载初始数据的选项。我们将看看Spring Boot的不同选项。
Spring Boot使管理任何类型的数据库变化变得非常容易。如果我们不定义任何自定义配置而使用默认配置,它将在我们的包中搜索实体并创建相应的表。我们可以使用Spring中的data.sql
和schema.sql
文件来获得对数据库改动的更多控制。这是一个强大的功能,可以让你在不同的环境中工作。让我们通过下面的例子看看如何在启动时加载这些初始数据。
为了用Spring Boot加载初始数据,我们可以使用Spring Boot内置的对JPA的支持。让我们假设我们有一个雇员实体,需要在数据库中初始化模式和样本数据。
public class Employee {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String employeeName;
private String salary;
private Date createdAt;
private Date updatedAt;
}
当我们运行应用程序时,Spring Boot将为我们创建一个空表,但不会为上述定义的实体填充该表。通过将Spring Boot配置文件中的spring.jpa.hibernate.ddl-auto
设置为create
或create-drop
,可以为你的实体自动创建模式。如果你将ddl-auto
设置为create或create-drop,Hibernate将根据你的实体的映射为其生成一个模式。你需要在你的application.properties
文件中添加以下属性。
spring.jpa.hibernate.ddl-auto=create
当ddl-auto
或create-drop
值被创建时,Hibernate会在类路径上寻找import.sql
,以便初始化数据。你可以在classpath上添加import.sql
文件。
INSERT INTO employee VALUES
('Steve', '50000', '2022-04-04 11:33:30', NULL);
('Bill', '55000', '2022-04-05 12:33:30', NULL);
('Mark', '30000', '2022-04-01 04:31:50', '2022-04-08 09:12:32');
('Josh', '60000', '2022-04-03 09:22:25', '2022-04-07 12:34:54');
上述方法,包括使用JPA实体,有其自身的缺点。在import.sql
文件中,每一行都应该包含一条SQL语句。为了使import.sql
发挥作用,它的每一行都应该有一条语句
顾名思义,我们需要在classpath上添加data.sql
文件。Spring Boot将扫描classpath,并在数据库更新操作中选择该文件。以下是该文件的样子。
INSERT INTO employee (employee_name, salary, created_at, updated_at)
VALUES ('Steve', '50000', '2022-04-04 11:33:30', NULL);
INSERT INTO employee (employee_name, salary, created_at, updated_at)
VALUES ('Bill', '55000', '2022-04-05 12:33:30', NULL);
INSERT INTO employee (employee_name, salary, created_at, updated_at)
VALUES ('Mark', '30000', '2022-04-01 04:31:50', '2022-04-08 09:12:32');
INSERT INTO employee (employee_name, salary, created_at, updated_at)
VALUES ('Josh', '60000', '2022-04-03 09:22:25', '2022-04-07 12:34:54');
用Spring Boot加载初始数据。
如果我们不想使用默认的模式创建机制,我们可以创建一个自定义的schema.sql文件,以便用Spring Boot加载初始数据。这个文件将被Spring Boot选中用于模式创建。
CREATE TABLE employee (
id INTEGER NOT NULL AUTO_INCREMENT,
employee_name varchar(45),
salary varchar(45) NOT NULL,
created_at datetime NOT NULL,
updated_at datetime DEFAULT NULL,
PRIMARY KEY (id)
);
注意,基于脚本的初始化,也就是schema.sql
和data.sql
,和hibernate初始化在一起会引起一些问题。
为了禁用Hibernate的自动创建,我们可以在application.properties
文件中添加以下属性。这个属性将确保基于Spring Boot脚本的初始化将直接使用schema.sql
和data.sql
。
spring.jpa.hibernate.ddl-auto=none
通过在application.proerties中设置以下属性,我们仍然可以同时拥有Hibernate自动模式生成和基于脚本的模式创建的共轭。
spring.jpa.defer-datasource-initialization=true
因此,一旦它完成模式创建,schema.sql
将被读取以获得任何额外的模式变化,data.sql
将被执行以填充数据库。data.sql
文件和schema.sql
文件中的任何变化也会影响到实际的数据库和表。默认执行基于脚本的初始化,但这只适用于嵌入式数据库。
如果你总是想用脚本初始化数据库,在application.properties
文件中添加spring.sql.init.mode=always
。
Spring Boot应用程序可以通过使用JDBC数据源创建DDL
脚本模式。数据源连接工厂自动创建并初始化DML脚本。这也是作为标准classpath扫描sql文件的一部分来加载SQL,即schema.sql
anddata.sql
.。
我们可以使用这个文件更新数据字段。
INSERT INTO employee (employee_name, salary, created_at, updated_at)
VALUES ('Steve', '50000', '2022-04-04 11:33:30', NULL);
我们还可以加载schema.sql
文件,如第1节所述,用Spring Boot加载初始数据。我们还可以处理schema-${platform}.sql
和data-${platform}.sql
(平台可以是oracle、MySQL、PostgreSQL)文件。如果需要的话,这允许在数据库特定的脚本之间进行切换。数据库初始化默认发生在嵌入式内存数据库上,尽管我们可以设置spring.sql.init
模式来always
初始化SQL数据库。它还默认启用了基于脚本的数据库初始化器的故障快速功能,也就是说,如果脚本抛出异常,应用程序就不能启动。
这些类型的基于脚本的数据源初始化是在创建任何EntityManagerFactory
豆子之前进行的。e1d34d1管理DDL并创建模式,而data.sql
管理DML并填充数据库。你也可以使用高级别数据库迁移工具,如flyway或Liquibase来创建和初始化模式。这些可以帮助你制作具有自定义名称的脚本。
Hibernate提供了一个JPA特定的属性来控制数据库的创建和执行DDL生成,这个属性是spring.jpa.hibernate.ddl-auto
。我们也可以使用这个属性来加载Spring Boot的初始数据。它有多个属性值,分别是*create
、update
、create-drop
、validate
*和<em>none</em>
。每一个都有不同的功能,以不同的方式控制数据库的创建。让我们看看它们各自是如何改变下面的DDL查询的。
*创建。Hibernate将删除所有现有的表,然后从头开始创建新的表。
*更新:它根据包括注释或XML
的映射创建对象。这与现有的模式进行比较,然后根据差异用于更新模式。它不会删除任何现有的表或删除任何列,即使它们不再被需要。它只会更新现有的模式,即改变数据类型并根据需要添加任何列。
.sql
文件中定义的表和列是否存在于数据库中。否则它将抛出一个异常。create-drop,
,否则其他情况下都没有。默认情况下,Spring Boot DataSource将自动用模式进行初始化。如果我们想改变或定制这种行为,用Spring Boot加载初始数据,我们可以使用spring.sql.init.mode
属性。这个属性有三个值。
MySQL
或PostgreSQL
,如果我们想初始化其模式,就有必要将此属性设置为始终。@Sql
注解提供了一种初始化和填充我们的测试模式的声明性方法。对于我们的集成测试,让我们创建一个新的表并使用@Sql annotation
加载它的初始数据。
@RunWith(SpringRunner.class)
@SpringBootTest
public class SpringBootInitialLoadIntegrationTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testLoadDataForTestClass() {
assertEquals(4, employeeRepository.findAll().size());
}
}
让我们看看***@SQL annotation
***的不同组件。
BEFORE_TEST_METHOD
或AFTER_TEST_METHOD
。@Test
@Sql({"/import_senior_employees.sql"})
public void testLoadDataForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
使用@SqlConfig
注解来加载Spring Boot的初始数据,我们可以配置SQL脚本如何被解析和运行。我们可以将类级配置声明为@SqlConfig
,在这里它可以作为类的全局设置。或者,我们可以用它来设置特定的@Sql
注释。下面是一个例子,我们指定了我们的SQL脚本的编码,以及执行它们的交易模式。
@Test
@Sql(scripts = {
"/import_senior_employees.sql"
},
config = @SqlConfig(encoding = "utf-8", transactionMode = TransactionMode.ISOLATED))
public void testLoadDataV1ForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
blockCommentStartDelimiter-这表示用来识别SQL脚本文件中块注释的开始的分隔符。
blockCommentEndDelimiter在SQL脚本文件中,它用于显示块注释的结束。
commentPrefix-用于识别单行注释的前缀
使用@SqlConfig
注解来加载Spring Boot的初始数据,我们可以配置SQL脚本的解析和运行方式。我们可以将类级配置声明为@SqlConfig
,在这里它可以作为类的全局设置。或者,我们可以用它来设置特定的@Sql
注释。下面是一个例子,我们指定了我们的SQL脚本的编码,以及执行它们的交易模式。
@Test
@Sql(scripts = {
"/import_senior_employees.sql"
},
config = @SqlConfig(encoding = "utf-8", transactionMode = TransactionMode.ISOLATED))
public void testLoadDataV1ForTestCase() {
assertEquals(5, employeeRepository.findAll().size());
}
blockCommentStartDelimiter-这表示用来识别SQL脚本文件中块注释的开始的分隔符。
blockCommentEndDelimiter在SQL脚本文件中,它用于显示块注释的结束。
commentPrefix-用于识别SQL脚本中单行注释的前缀。
dataSource-它将针对javax.sql.DataSource
bean运行XML脚本和SQL语句。
encoding-这表示SQL脚本文件将使用的编码。默认情况下,它与平台的编码相同。
errorMode-这个模式代表在运行脚本时发生错误时将使用的errorMode
。
separator-这定义了用于分隔不同的单独语句的字符串。默认情况下使用"-"。
transactionManager-这定义了事务使用的PlatformTransactionManager的豆子名称。
transactionMode-在事务中执行任何脚本时使用。
在Java 8及以上版本中,支持多个注解。我们可以使用这个功能,用Spring Boot加载初始数据的@Sql
注解。对于Java 7及以下版本,有一个容器注解叫@SqlGroup
。我们可以通过使用@SqlGroup
注解来声明多个@Sql
注解。
@SqlGroup({
@Sql(scripts = "/employees_schema.sql",
config = @SqlConfig(transactionMode = TransactionMode.ISOLATED)),
@Sql("/import_employees.sql")
})
public class SpringBootSqlGroupAnnotationIntegrationTest {
@Autowired
private EmployeeRepository employeeRepository;
@Test
public void testLoadDataForTestCase() {
assertEquals(4, employeeRepository.findAll().size());
}
}
在这篇文章中,我们看到了如何使用不同的方法来加载Spring Boot的初始数据。我们学习了如何通过使用schema.sql
和data.sql
文件来设置模式并将数据填充其中。此外,我们研究了如何使用@Sql
、@SqlConfig
和@SqlGroup
注释为测试加载测试数据。需要注意的是,这种方法更适合于基本和简单的场景。任何高级的数据库处理都需要更高级、更完善的工具,如Liquibase和Flyway。一如既往,你可以查看我们的GitHub repository的最新源代码。
版权说明 : 本文为转载文章, 版权归原作者所有 版权申明
原文链接 : https://www.javadevjournal.com/spring-boot/loading-initial-data-with-spring-boot/
内容来源于网络,如有侵权,请联系作者删除!