乐趣区

关于spring:SpringBoot系列之数据库初始化datasource配置方式

【DB 系列】数据库初始化 -datasource 配置形式 | 一灰灰 Blog

在咱们的日常业务开发过程中,如果有 db 的相干操作,通常咱们是间接建设好对应的库表构造,并初始化对应的数据,即更常见的状况下是咱们在已有表构造根底之下,进行开发;
然而当咱们是以我的项目模式工作时,更常见的做法是所有的库表构造变更、数据的初始、更新等都须要持有对应的 sql 变更,并保留在我的项目工程中,这也是应用 liqubase 的一个重要场景;
将下面的问题进行简略的翻译一下,就是如何实现在我的项目启动之后执行相应的 sql,实现数据库表的初始化?

本文将作为初始化形式的第一篇:基于 SpringBoot 的配置形式实现的数据初始化

<!– more –>

I. 我的项目搭建

1. 依赖

首先搭建一个规范的 SpringBoot 我的项目工程,相干版本以及依赖如下

本我的项目借助 SpringBoot 2.2.1.RELEASE + maven 3.5.3 + IDEA 进行开发

<dependencies>
    <dependency>
        <groupId>mysql</groupId>
        <artifactId>mysql-connector-java</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-jdbc</artifactId>
    </dependency>
</dependencies>

本文应用 MySql 数据库, 版本 8.0.31

2. 配置

留神实现初始化数据库表操作的外围配置就在上面,重点关注

配置文件:resources/application.yml

# 默认的数据库名
database:
  name: story

spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/${database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password:
    initialization-mode: always
    platform: mysql
    separator: ;
    data: classpath:config-data.sql
    #data-username: root
    #data-password:
    schema: classpath:config-schema.sql # schema 必须也存在,若只存在 data,data 中的 sql 也不会被执行

# springboot 2.7+ 版本应用上面这个
#  sql:
#    init:
#      mode: always
#      data-location: classpath:config-data.sql
#      schema-location: classpath:init-schema.sql
logging:
  level:
    root: info
    org:
      springframework:
        jdbc:
          core: debug

下面的配置中,相比拟于一般的数据库链接配置,多了几个配置项

  • spring.datasource.initialization-mode: 取值为 always,改成其余的会导致 sql 不会被执行
  • spring.datasource.platform: mysql
  • spring.datasource.seprator: ; 这个示意 sql 之间的分隔符
  • spring.datasource.data: classpath:config-data.sql 取值能够是数组,这里存的是初始化数据的 sql 文件地址
  • spring.datasource.data-username: 下面 data 对应的 sql 文件执行用户名
  • spring.datasource.data-password: 下面 data 对应的 sql 文件执行用户明码
  • spring.datasource.schema: classpath:config-schema.sql 取值也能够是数组,这里存的是初始化表构造的 sql 文件地址

3. 初始化 sql

下面指定了两个 sql,一个是用于建表的 ddl,一个是用于初始化数据的 dml

resources/config-schema.sql 文件对应的内容如下

CREATE TABLE `user2`
(
    `id`               int unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
    `third_account_id` varchar(128) NOT NULL DEFAULT ''COMMENT' 第三方用户 ID',
    `user_name`        varchar(64)  NOT NULL DEFAULT ''COMMENT' 用户名 ',
    `password`         varchar(128) NOT NULL DEFAULT ''COMMENT' 明码 ',
    `login_type`       tinyint      NOT NULL DEFAULT '0' COMMENT '登录形式: 0- 微信登录,1- 账号密码登录',
    `deleted`          tinyint      NOT NULL DEFAULT '0' COMMENT '是否删除',
    `create_time`      timestamp    NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创立工夫',
    `update_time`      timestamp    NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '最初更新工夫',
    PRIMARY KEY (`id`),
    KEY                `key_third_account_id` (`third_account_id`),
    KEY                `user_name` (`user_name`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb4  COMMENT='用户登录表';

resources/config-data.sql 文件对应的内容如下

INSERT INTO `user2` (id, third_account_id, `user_name`, `password`, login_type, deleted)
VALUES (2, '222222-0f85-4dd5-845c-7c5df3746e92', 'admin2', 'admin2', 0, 0);

II. 示例

1. 验证 demo

接下来下面的工作筹备结束之后,在咱们启动我的项目之后,失常就会执行下面的两个 sql,咱们写一个简略的验证 demo

@Slf4j
@SpringBootApplication
public class Application implements ApplicationRunner {
    @Autowired
    private JdbcTemplate jdbcTemplate;

    public static void main(String[] args) {SpringApplication.run(Application.class);
    }

    @Override
    public void run(ApplicationArguments args) throws Exception {List list = jdbcTemplate.queryForList("select * from user2 limit 2");
        log.info("启动胜利,初始化数据: {}\n{}", list.size(), list);
    }
}

2. 问题记录

从下面的过程走下来,看起来很简略,然而在理论的应用过程中,很容易遇到不失效的问题,上面记录一下

2.1 只有初始化数据 data.sql,没有 schema.sql 时,不失效

当库表曾经存在时,此时咱们可能并没有上文中的 config-schema.sql 文件,此时对应的配置可能是


spring:
  datasource:
    url: jdbc:mysql://127.0.0.1:3306/${database.name}?useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
    username: root
    password:
    initialization-mode: always
    platform: mysql
    separator: ; # 默认为 ;
    data: classpath:config-data.sql
    #data-username: root
    #data-password:
    #schema: classpath:config-schema.sql # schema 必须也存在,若只存在 data,data 中的 sql 也不会被执行

如下面所示,当咱们只指定了 data 时,会发现 data 对应的 sql 文件也不会被执行;即要求 schema 对应的 sql 文件也必须同时存在

针对下面这种状况,能够思考将 data.sql 中的语句,卸载 schema.sql 中

2.2 版本问题导致配置不失效

在 SpringBoot2.5+ 版本,应用 spring.sql.init 代替下面的配置项

# springboot 2.5+ 版本应用上面这个
spring:
  sql:
    init:
      mode: always
      data-location: classpath:config-data.sql
      schema-location: classpath:init-schema.sql

相干的配置参数阐明如下

  • spring.sql.init.enabled:是否启动初始化的开关,默认是 true。如果不想执行初始化脚本,设置为 false 即可。通过 - D 的命令行参数会更容易管制。
  • spring.sql.init.usernamespring.sql.init.password:配置执行初始化脚本的用户名与明码。这个十分有必要,因为平安治理要求,通常给业务利用调配的用户对一些建表删表等命令没有权限。这样就能够与 datasource 中的用户离开治理。
  • spring.sql.init.schema-locations:配置与 schema 变更相干的 sql 脚本,可配置多个(默认用; 宰割)
  • spring.sql.init.data-locations:用来配置与数据相干的 sql 脚本,可配置多个(默认用; 宰割)
  • spring.sql.init.encoding:配置脚本文件的编码
  • spring.sql.init.separator:配置多个 sql 文件的分隔符,默认是;
  • spring.sql.init.continue-on-error:如果执行脚本过程中碰到谬误是否持续,默认是 false`

2.3 mode 配置不对导致不失效

当配置完之后发,发现 sql 没有依照预期的执行,能够检查一下 spring.datasource.initialization-mode 配置是否存在,且值为always

2.4 反复启动之后,报错

同样下面的我的项目,在第一次启动时,会执行 schema 对应的 sql 文件,创立表构造;执行 data 对应的 sql 文件,初始化数据;然而再次执行之后就会报错了,会提醒表曾经存在

即初始化是一次性的,第一次执行结束之后,请将 spring.datasource.initialization-mode 设置为none

3. 小结

本文次要介绍了我的项目启动时,数据库的初始化形式,当然除了本文中介绍的 spring.datasource 配置之外,还有 spring.jpa 的配置形式

对于配置形式不太敌对的中央则在于不好自适应控制,若表存在则不执行;若不存在则执行;前面将介绍如何应用 DataSourceInitializer 来实现自主可控的数据初始化,以及更现代化一些的基于 liquibase 的数据库版本治理记录

III. 不能错过的源码和相干知识点

0. 我的项目

  • 工程:https://github.com/liuyueyi/spring-boot-demo
  • 源码:https://github.com/liuyueyi/spring-boot-demo/tree/master/spring-boot/161-schema-init

1. 微信公众号: 一灰灰 Blog

尽信书则不如,以上内容,纯属一家之言,因集体能力无限,不免有疏漏和谬误之处,如发现 bug 或者有更好的倡议,欢送批评指正,不吝感谢

上面一灰灰的集体博客,记录所有学习和工作中的博文,欢送大家前去逛逛

  • 一灰灰 Blog 集体博客 https://blog.hhui.top
  • 一灰灰 Blog-Spring 专题博客 http://spring.hhui.top
退出移动版