写点什么

Spring Boot「06」Loading initial data

作者:Samson
  • 2022-10-15
    上海
  • 本文字数:2683 字

    阅读完需:约 1 分钟

Spring Boot「06」Loading initial data

开发过程中,在对某些服务进行单元测试时离不开对数据库的依赖。此时,我们在测试时需要使用内存数据库搭配建表、插表语句来为服务提供基本的测试数据。今天,我们将来看一下 Spring Boot 中如何在启动时创建、并加载初始数据。

01-初始化数据库的方式

  1. 使用 JPA

  2. spring.jpa.generate-ddl=true|false 属性来控制是否开启 DDL 生成

  3. 使用 Hibernate

  4. spring.jpa.hibernate.ddl-auto=none|validate|update|create|create-drop 属性来控制使用 Hibernate 初始化数据库时的行为。在使用内存数据库(例如 h2/hsqldb/derby)时,该属性存在一个默认值:未检测到 schema manager 时,默认值为 create-drop;其他情况,默认值为 none。当上述属性值为 create 或 crate-drop 时,Hibernate 在启动时还会读取 classpath 根目录下的 import.sql 并执行(不过注意:这是 Hibernate 的特性,并非 Spring 的)。

  5. 使用 SQL Scripts

  6. Spring Boot 会加载 classpath 根目录下的 schema.sql 和 data.sql;

  7. spring.sql.init.platform=platform_value 属性可以使 Spring Boot 加载 schema-{platform_value}.sql,其中 platform_value 可以是 mysql/oracle/h2 等等;

  8. 默认情况下,只有在使用内存数据库时,Spring Boot 才会加载上述的 SQL Scripts,这个行为可以通过属性 spring.sql.init.mode=always|never|embedded 来控制:always 指使用任何数据库时都初始化数据库,never 指从不初始化数据库,embedded 指使用内存数据库时初始化数据库;

  9. 默认情况下,Spring Boot 执行 SQL Scripts 时是 fail-fast 的,这个行为可以通过属性spring.sql.init.continue-on-error=true|false调整;

  10. 默认情况下,使用 SQL Scripts 初始化数据库发生在 JPA EntityManagerFactory Bean 创建之前。尽管不推荐方式 1-3 中的多种初始化方式混合使用,但是如果想在 Hibernate 自动生成 DDL 的基础上再执行 schema.sql 和 data.sql,可以将属性spring.jpa.defer-datasource-initialization设置为 true。意味着将 SQL Scripts 的执行事件延迟(defer)到 EntityManagerFactory Bean 创建之后。schema.sql 可以在 Hibernate 生成的 DDL 基础上做额外的动作,data.sql 可以用来填充数序。


spring.jpa.hibernate.ddl-auto不同取值的含义:


  • create,如果表格已存在,则先删除,然后创建新的表格;

  • update,修改已存在的 schema,并不会删除任何表或列,即使它们不再被应用使用;

  • create-drop,与 create 类似,只不过在所有操作都完成以后,会删掉数据库,一般用于 unit test

  • validate,仅验证表和列是否存在;若不存在,则抛异常;

  • none,指不开启 DDL 自动生成


[1] Database Initialization

02-内存数据库 H2

接下来,我们用上节中介绍的第 2、3 种方法,搭配 H2 数据库,演示一下 Spring Boot 是如何初始化数据库的。首先,在 pom.xml 中引入 h2 和 spring-boot-starter-data-jpa 依赖:


<dependency>    <groupId>com.h2database</groupId>    <artifactId>h2</artifactId>    <version>2.1.214</version>    <scope>runtime</scope></dependency><dependency>    <groupId>org.springframework.boot</groupId>    <artifactId>spring-boot-starter-data-jpa</artifactId>    <version>2.7.4</version></dependency>
复制代码


接下来,在 application.properties 中配置内存数据库。


spring.datasource.url=jdbc:h2:mem:testdbspring.datasource.driverClassName=org.h2.Driverspring.datasource.username=saspring.datasource.password=passwordspring.jpa.database-platform=org.hibernate.dialect.H2Dialect
复制代码


jdbc:h2:mem:testdb 指使用内存数据库(易失),数据库名为 testdb。如果需要将数据库持久化在磁盘上,可以将mem:testdb修改为file:/data/file/path。然后,创建一个 Entity 类 Country,它存储在 COUNTRY 表中。


@Entity@Table(name = "COUNTRY")public class Country {    @Id    @GeneratedValue(strategy = IDENTITY)    private Integer id;    @Column(nullable = false)    private String name;    // ... constructor & getters & setters}
复制代码


接下来,我们先只使用 Hibernate(即上节中的第 2 种方法)来自动生成数据库表。开启自动生成功能,需要在 application.properties 中增加 spring.jpa.hibernate.ddl-auto=create-drop。到目前为止,运行程序就会在内存数据库中创建 COUNTRY 表。Hibernate 会使用 org.hibernate.SQL logger 打印建表语句,如果要从日志中看到,需要在 application.properties 中增加debug=true,如下所示:


org.hibernate.SQL: drop table if exists country CASCADE org.hibernate.SQL: create table country (id integer generated by default as identity, name varchar(255) not null, primary key (id))
复制代码


为了方便查询 h2 数据库的状态,我们打开 H2 内置的 GUI 控制台,只需要在 application.properties 中添加spring.h2.console.enabled=true。然后就可以通过浏览器访问 http://localhost:8080/h2-console,如下所示:



输入之前配置的数据库连接信息即可登录。


配置完成后,我们将上节中介绍的 SQL Scripts(即第 3 种方法)在 Hibernate 生成的 schema 基础上再通过 schema.sql 和 data.sql 完成数据库的初始化。首先,我们需要在 application.properties 中添加spring.jpa.defer-datasource-initialization=true,表示我们将 SQL Scripts 的初始化延迟到 Hibernate 之后。然后,在 resources 下添加 schema.sql:


CREATE TABLE IF NOT EXISTS country (     id   INTEGER      NOT NULL AUTO_INCREMENT,     name VARCHAR(128) NOT NULL,     PRIMARY KEY (id));
复制代码


再添加 data.sql,向创建的表格中插入 5 条数据:


INSERT INTO COUNTRY (id, name) VALUES (1, 'USA');INSERT INTO COUNTRY (id, name) VALUES (2, 'France');INSERT INTO COUNTRY (id, name) VALUES (3, 'Brazil');INSERT INTO COUNTRY (id, name) VALUES (4, 'Italy');INSERT INTO COUNTRY (id, name) VALUES (5, 'Canada');
复制代码


好了,到此为止,所有的准备工作就都完成啦。让我们来运行下程序,看看效果吧。登录到 h2-console 之后,使用select * from country;查询 data.sql 中的数据有没有插入到数据库中,结果如下所示:



[1] Spring Boot With H2 Database

03-总结

今天,我们学习了 Spring Boot 中加载初始化数据的三种方式,并且以 Hibernate + SQL Scripts 配合的方式,搭配 H2 内存数据库,演示了整个过程。这种加载初始化数据的方式在做的单元测试是非常有用,可以提高测试效率。

发布于: 刚刚阅读数: 6
用户头像

Samson

关注

还未添加个人签名 2019-07-22 加入

InfoQ签约作者 | 阿里云社区签约作者

评论

发布
暂无评论
Spring Boot「06」Loading initial data_Java_Samson_InfoQ写作社区